How write stub method with NUnit in C#
Solution 1
A good way to allow you to write stubs is to use dependency injection. FirstDeep
depends on SecondDeep
and in your test you want to replace SecondDeep
with a stub.
First change your existing code by extracting an interface for SecondDeep
and then inject that into FirstDeep
in the constructor:
interface ISecondDeep {
Boolean SomethingToDo(String str);
}
class SecondDeep : ISecondDeep { ... }
class FirstDeep {
readonly ISecondDeep secondDeep;
public FirstDeep(ISecondDeep secondDeep) {
this.secondDeep = secondDeep;
}
public String AddA(String str) {
var flag = this.secondDeep.SomethingToDo(str);
...
}
}
Note that FirstDeep
no longer creates a SecondDeep
instance. Instead an instance is injected in the constructor.
In your test you can create a stub for ISecondDeep
where SomethingToDo
always returns true:
class SecondDeepStub : ISecondDeep {
public Boolean SomethingToDo(String str) {
return true;
}
}
In the test you use the stub:
var firstDeep = new FirstDeep(new SecondDeepStub());
In production code you use the "real" SecondDeep
:
var firstDeep = new FirstDeep(new SecondDeep());
Using a dependency injection container and a stubbing framework can make a lot of this easier to do.
If you don't want to rewrite your code you can use a framework for intercepting calls like Microsoft Moles. In the next version of Visual Studio a similar technology will be available in the Fakes Framework.
Solution 2
To make your code testable, do not instantiate dependencies inside your class. Use dependency injection (via constructor, property or parameter). Also use abstract classes or interfaces to allow mocking of dependencies:
class FirstDeep
{
private ISecondDeep oa;
public FirstDeep(ISecondDeep oa)
{
this.oa = oa;
}
public string AddA(string str)
{
return String.Concat(str, oa.SomethingToDo(str) ? "AAA" : "BBB");
}
}
Depending on abstractions allows you to test your class in isolation.
interface ISecondDeep
{
bool SomethingToDo(string str);
}
class SecondDeep : ISecondDeep
{
public bool SomethingToDo(string str)
{
bool flag = false;
if (str.Length < 10)
{
// without abstraction your test will require database
}
return flag;
}
}
Here is test sample (using Moq). It shows you how you can return true
from call to your mocked dependency:
[TestFixture]
class Tests
{
[Test]
public void AddAAATest()
{
// Arrange
Mock<ISecondDeep> secondDeep = new Mock<ISecondDeep>();
secondDeep.Setup(x => x.SomethingToDo(It.IsAny<string>())).Returns(true);
// Act
FirstDeep fd = new FirstDeep(secondDeep.Object);
// Assert
Assert.That(fd.AddA("ABD"), Is.EqualTo("ABCAAA"));
}
}
Related videos on Youtube
Comments
-
Smit almost 2 years
I have 2 classes:
- FirstDeep.cs
SecondDeep.cs
I did simple code for example:
class FirstDeep { public FirstDeep() { } public string AddA(string str) { SecondDeep sd = new SecondDeep(); bool flag = sd.SomethingToDo(str); if (flag == true) str = string.Concat(str, "AAA"); else str = string.Concat(str, "BBB"); return str; } }
and
class SecondDeep { public bool SomethingToDo(string str) { bool flag = false; if (str.Length < 10) { //todo something in DB, and after that flag should be TRUE } return flag; } }
Then I want to write unit test for method "AddA":
class Tests { [Test] public void AddATest() { string expected = "ABCAAA"; FirstDeep fd = new FirstDeep(); string res = fd.AddA("ABC"); Assert.AreEqual(expected, res); } }
And after that I have trouble, I don't know how correct write stub for method SomethingToDo in my Test class. I always have false. I should just return TRUE. But how?