I have a class similiar to this:
public class MyClass
{
public Task MyMethod()
{
//do something
}
}
As described, 'MyMethod' is asynchronous, lets say for simplicity that this is it's implementation:
public Task MyMethod()
{
return Task.Run(() =>
{
var success = _someService.DoSomething();
if (!success) throw new Exception("unsuccsesfull");
});
}
Obviously, when MyMethod awaitable callback will run it means that no exception was thrown in the running thread, meaning 'MyMethod' invocation was successfull.
I want to test this method. The test method to will look like:
[Test]
public async void TestMyMethod_TestInitialState_TestExpectedResult()
{
// test initialization..
//...
//..
var myClass = new MyClass();
await myClass.MyMethod();
Assert.That(????)
}
My question - what is the correct assertion?
I have a possible solution - add a logical member to 'MyClass' and update this member according to the method result:
public class MyClass
{
public bool SomeMember { get; private set; }
public Task MyMethod()
{
Task.Run(() =>
{
SomeMember = _someService.DoSomething();
if (!SomeMember ) throw new Exception("unsuccsesfull");
});
}
}
That way I can assert the test like this:
[Test]
public async void TestMyMethod_TestInitialState_SomeMemberShouldBeTrue()
{
// test initialization..
//...
//..
var myClass = new MyClass();
await myClass.MyMethod();
Assert.True(SomeMember)
}
}
However, I dont like this solution because I'm adding a property to 'MyClass' just to be able to assert a test, I dont really need this property in my bussiness world. Also each property added to a class represents some state of this class and adds a level of comlexity.
Suggestions?
Guy.
You want what's called a "mock" or "stub". The idea is that you refactor your code so that it has a dependency on an interface, then you mock the interface while testing.
There are various frameworks/tools that help out with mocking (Moq, Microsoft Fakes, TypeMock Isolator, JustMock, etc), and there are also many frameworks that help out with the closely related problem of dependency injection (Unity, Castle Windsor, StructureMap, Autofac, etc).
But you can start off just doing it yourself. First, refactor MyClass so it depends on ISomeService:
public interface ISomeService
{
bool DoSomething();
}
public class MyClass
{
private readonly ISomeService _someService;
public MyClass(ISomeService someService)
{
_someService = someService;
}
public Task MyMethod()
{
return Task.Run(() =>
{
var success = _someService.DoSomething();
if (!success) throw new Exception("unsuccsesfull");
});
}
}
Then in your unit test:
private class TestService : ISomeService
{
public bool DoSomethingReturnValue { get; set; }
public bool DoSomething() { return DoSomethingReturnValue; }
}
[Test]
public async Task TestMyMethod_TestInitialState_TestExpectedResult()
{
var myClass = new MyClass(new TestService { DoSomethingReturnValue = true });
await myClass.MyMethod();
}
[Test]
public async Task TestMyMethod_TestInitialState_TestFailure()
{
var myClass = new MyClass(new TestService { DoSomethingReturnValue = false });
Assert.Throws(() => myClass.MyMethod()); // (I'm unsure of the exact NUnit syntax)
}
Related
I have an interface with a method like this:
public string GetImageSrc(string input);
The implementation of this is below:
public string GetImageSrc(string input)
{
if (input.ContainsImage())
{
DoWork();
}
return input;
}
My string extension for ConatinsImage is:
public static bool ContainsImage(this string input)
{
if (!string.IsNullOrEmpty(input))
{
return input.Contains("img");
}
return false;
}
DoWork is a private method in the class. I am writing Unit Tests for the class - I am passing null to the method and doing an assert that null is returned. However is there a way I can Assert the invocation of the DoWork private method is None for a null input?
I recommend creating a new interface IWorker with a DoWork() method, then inject it into the constructor of the class that contains the GetImageSrc() method. In your unit test, you could then inject a mock object of the interface, and verify DoWork() was called or not:
public interface IWorker
{
void DoWork();
}
public class YourClass
{
private readonly IWorker _worker;
public YourClass(IWorker worker)
{
_worker = worker;
}
public string GetImageSrc(string input)
{
if (input.ContainsImage())
{
_worker.DoWork();
}
return input;
}
}
Test using Microsoft.VisualStudio.TestTools.UnitTesting and Moq:
[TestMethod]
public void GetImageSrc_GivenNull_ReturnsNull_And_WorkerNotCalled()
{
var mockWorker = new Mock<IWorker>();
var testSubject = new YourClass(mockWorker.Object);
var response = testSubject.GetImageSrc(null);
Assert.IsNull(response);
mockWorker.Verify(x => x.DoWork(), Times.Never());
}
I want to mock only some methods of a class and call the real implementation for other methods.
I have my sut class Test where the Runner class is injected in the constructor. This injected class has again a injected other class RunnerParam in the constructor.
The code is a simplified case of my real classes in trying to have only the basics.
[Fact]
public void Test()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var paramMock = fixture.Freeze<Mock<IRunnerParam>>();
paramMock.Setup(x => x.Multiplicator()).Returns(2);
var classMock = fixture.Freeze<Mock<IRunner>>();
classMock.Setup(x => x.Run()).Returns(5);
var test = fixture.Create<Test>();
var result = test.StartRunning(); // should be 5
var result2 = test.StartRunningImplementation(5); // should be 500
}
Supporting members
public interface IRunnerParam
{
int Multiplicator();
}
public class RunnerParam : IRunnerParam
{
public virtual int Multiplicator()
{
return 20;
}
}
public interface IRunner
{
int Run();
int RunImplementation(int param);
}
public class Runner : IRunner
{
protected virtual RunnerParam MultiParam { get; set; }
public Runner(RunnerParam multiParam)
{
MultiParam = multiParam;
}
public virtual int Run()
{
return 10;
}
public int RunImplementation(int param)
{
return 10 * MultiParam.Multiplicator() * param * Run();
}
}
public class Test
{
private readonly IRunner _runner;
public Test(IRunner runner)
{
_runner = runner;
}
public int StartRunning()
{
return _runner.Run();
}
public int StartRunningImplementation(int param)
{
return _runner.RunImplementation(param);
}
}
I want to mock and give a mocked value to the method Run in the class Runner, but to use the real implementation of the method RunImplementation.
I would expect to see for result2 500, but it's 0, meaning that the method is not seen as mocked up. In my eyes that is correct, but the Moq callbase is equal to true, so the real implementation should be taken, but it isn't.
What am I missing here?
In the shown simplified example, Test is only dependent on IRunner
private readonly IRunner _runner;
public Test(IRunner runner)
{
_runner = runner;
}
So that is all that needs to be mocked if the intention was to test Test class in isolation.
//...
var classMock = fixture.Freeze<Mock<IRunner>>();
classMock.Setup(x => x.Run()).Returns(5);
classMock.Setup(x => x.RunImplementation(It.IsAny<int>())).Returns(500);
//...
If Runner class is to be also tested in isolation, then a mocked RunnerParam would be needed to satisfy its dependencies.
It should however be dependent on the abstraction (interface) and not the concretion (implementation).
protected virtual IRunnerParam MultiParam { get; set; }
public Runner(IRunnerParam multiParam) {
MultiParam = multiParam;
}
This simplifies the isolated test as described in the original question
I want to mock and give a mocked value to the method Run in the class Runner, but to use the real implementation of the method RunImplementation.
//Arrange
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var runnerParam = fixture.Freeze<Mock<IRunnerParam>>()
.Setup(_ => _.Multiplicator())
.Returns(2);
var subjectMock = fixture.Freeze<Mock<Runner>>();
subjectMock.CallBase = true;
subjectMock.Setup(_ => _.Run()).Returns(5);
int expected = 500;
Runner sut = subjectMock.Object;
//Act
var actual = sut.RunImplementation(5); // should be 500
//Assert
actual.Should().Be(expected);
I have the below code :
public interface Iinterface
{
Task<bool> RetrieveFromDataBase();
}
public class Class1 : Iinterface
{
public async Task<bool> RetrieveFromDataBase()
{
//do something
return true;
}
}
public class AnotherClass
{
Class1 c = new Class1();
public AnotherClass(Class1 obj)
{
c = obj;
}
public async Task<bool> ExecuteData()
{
var result = await c.RetrieveFromDataBase();
if (result)
{
//do some calculation
}
return true;
}
}
Now, I'm trying to write test cases for ExecuteData method. In this method I need to bypass RetrieveFromDataBase method. So I'm trying to mock it. This is the below code I have written.
[TestClass()]
public class AnotherClassTests
{
[TestMethod()]
public async Task ExecuteDataTest()
{
Task<bool> retValue = RetrieveFromDataBaseMoq(); // this returns true
var moq = new Mock<Iinterface>();
moq.Setup(x => x.RetrieveFromDataBase()).Returns(retValue);
AnotherClass obj = new AnotherClass((Class1)moq.Object); // error thrown from here
var result = await obj.ExecuteData();
Assert.IsTrue(result);
}
}
The mocking which is done is successful, i.e it doesn't throw any error. The problem I'm facing here is when I pass this mocked object a parameter to the constructor, it is throwing error System.InvalidCastException : Unable to cast object "Castle.Proxies.Iinterface" to type "Class1".
I know that it is not able to convert mocked interface to the concrete class type. But is there a way to rectify this error or pass the mocked object to the main class in anyway.
Many thanks!
you should declare variable c as an Iinterface. That's one of the advantages of using interfaces. You should dependend on the contract(interface) , instead of concrete implementations. Following that you are not coupled to concrete classes.
public class AnotherClass
{
Iinterface c; //I removed the default new since it will get assigned in constructor
public AnotherClass(Iinterface obj)
{
c = obj;
}
public async Task<bool> ExecuteData()
{
var result = await c.RetrieveFromDataBase();
if (result)
{
//do some calculation
}
return true;
}
}
The problem here I'm facing is, the class Class1 has some other methods and variables as well which are not declared in the interface.
You could do a composition inside Class1, and move the TInterface as a dependency inside Class1. Keep in mind that the interface is what you will get mocked in unit test
public class Class1
{
public TIinterface tinterface{get;private set;}
public Class1(TIinterface interface)
{
tinterface= interface;
}
}
public class YourCustomImplementation:TIinterface
{
public async Task<bool> RetrieveFromDataBase()
{
//do something
return true;
}
}
public class AnotherClass
{
Class1 c = new Class1();
public AnotherClass(Class1 obj)
{
c = obj;
}
public async Task<bool> ExecuteData()
{
var result = await c.tinterface.RetrieveFromDataBase();
if (result)
{
//do some calculation
}
return true;
}
}
class CurrentClass
{
public Task OnStep()
{
this.Property = ClassStatic.Method();
}
}
I have 2 problem :
Cannot mock the ClassStatic.Method() because it is static.
If i can mock the ClassStatic, how to the OnStep() method call ClassStatic.Method() that i was mocked
Sorry about my english!!!
Use Microsoft Shims to test static methods. But usually a good idea not to use static classes and methods. Use dependency injection like so:
class MyClass
{
IUtility _util;
public MyClass(IUtility util)
{
_util = util;
}
public Task OnStep()
{
this.Property = _util.Method();
}
}
public TestMethod()
{
IUtility fakeUtil = Mock.Of<IUtility>();
MyClass x = new MyClass(fakeUtil);
}
But if you want to use the static class instead use the shims:
using (ShimsContext.Create())
{
// Arrange:
// Shim ClassStatic.Method to return a fixed date:
Namespace.ShimClassStatic.Method =
() =>
{
// This will overwrite your static method
// Fake method here
};
// Instantiate the component under test:
var componentUnderTest = new MyComponent();
// Act:
// Assert:
}
In the following example, I want to test the TestMe.DoSomething() function.
I want to mock the ISomething interface that is used within this method and make it return different values (depending on the specific unit test.)
In real life the ISomething interface winds up calling out to expensive 3rd party resources -- I definitely don't want to just call a real ISomething.
Here is the example structure:
class TestMe
{
public void DoSomething()
{
ISomething s = SomethingFactory();
int i = s.Run();
//do things with i that I want to test
}
private ISomething SomethingFactory()
{
return new Something();
}
}
interface ISomething
{
int Run();
}
class Something : ISomething
{
public int Run()
{
return 1;
}
}
Here is code that doesn't work:
var fakeSomething = new Mock<ISomething>();
var testMe = new TestMe();
Mock.Get(testMe).Setup(p => p.SomethingFactory()).Returns(fakeSomething.Object);
testMe.DoSomething();
Because SomethingFactory() is private, I cannot set the return value from that method to be what I want.
Any advice on how I can solve this?
Make the factory a full interface / class and remove the SomethingFactory method from TestMe.
public interface ISomethingFactory {
ISomething MakeSomething();
}
public sealed class SomethingFactory {
public ISomething MakeSomething() {
return new Something();
}
}
class TestMe
{
private readonly ISomethingFactory _somethingFactory;
public TestMe(ISomethingFactory somethingFactory) {
_somethingFactory = somethingFactory;
}
public void DoSomething()
{
ISomething s = _somethingFactory.MakeSomething();
int i = s.Run();
//do things with i that I want to test
}
}
This will allow you to mock ISomethingFactory to return a mock of ISomething.
While I think you may protest this solution as too drastic a change, I think its better than making a class that's not sealed with a members who's only reason for being virtual is for testing.
You can inject your dependency. If you don't want to break all your callers you can add two constructors and use the one that lets you inject fake in tests
class TestMe
{
private readonly ISomething something;
TestMe() : this(new RealSomething()
{
}
TestMe(ISomething sth)
{
something = sth;
}
public void DoSomething()
{
ISomething s = SomethingFactory();
int i = s.Run();
//do things with i that I want to test
}
private ISomething SomethingFactory()
{
return new Something();
}
}
Second way would be to change the
SomethingFactory
method to protected virtual and override it in derived class and use that class instead, or to setup
class TestableTestMe : TestMe
{
private readonly ISomething something;
TestableTestMe(ISomething testSpecific)
{
something = testSpecific;
}
public void DoSomething()
{
ISomething s = SomethingFactory();
int i = s.Run();
//do things with i that I want to test
}
protected override ISomething SomethingFactory()
{
return something;
}
}
This technique is called "extract and override"
Changing SomethingFactory() to be protected virtual allows you to use Moq.Protected to access the method by its name:
public class TestMe
{
public void DoSomething()
{
ISomething s = SomethingFactory();
int i = s.Run();
//do things with i that I want to test
}
protected virtual ISomething SomethingFactory()
{
return new Something();
}
}
public interface ISomething
{
int Run();
}
public class Something : ISomething
{
public int Run()
{
return 1;
}
}
So you can run this test:
var fakeSomething = new Mock<ISomething>();
fakeSomething.Setup(p => p.Run()).Returns(2);
var testMe = new Mock<TestMe>();
testMe.Protected().Setup<ISomething>("SomethingFactory").Returns(fakeSomething.Object);
testMe.Object.DoSomething();