I'm trying to be a good developer and actually right some unit tests for some code I have written.
I am using NUnit with Ninject.MockingKernel.Moq and followed the documentation on https://github.com/ninject/ninject.mockingkernel/wiki/Examples. Here is an example of what I have been working with
[TestFixture]
public class MyUnitTest
{
private readonly MoqMockingKernel _kernel;
public MyUnitTest()
{
_kernel = new MoqMockingKernel();
}
[SetUp]
public void SetUp()
{
_kernel.Reset(); // Not really sure why this is included (something to do with caching...)
}
[Test]
public void MyTest()
{
var moqService = _kernel.GetMock<IMyService>();
moqService.Setup(x=>x.MyMethod("With parameter")
.Returns(new MyObject {Id = 1, Name = "With parameter"});
var service = _kernel.Get<IMyService>();
service.MyMethod("With parameter");
moqService.VerifyAll();
}
}
Now, to my amazement this actually works but is it actually testing the logic in the code? Or is it saying when you return this method this is what will be returned?
I did a small test, MyMethod returns an object:
var method = service.MyMothod("With parameter");
Debugged the test and method.Id does in fact equal 1 so I'm 75% certain it's working but I thought it best to check with someone more knowledgeable than myself!
If your goal is to test a IMyService that you implemented elsewhere, you are doing it wrong. What you are doing is creating a mock IMyService and testing that it is correctly mocked, which achieves not much.
You should use kernel.GetMock() if you need an IFoo to test your IMyService because your implementation of IMyService takes a IFoo as a parameter of its constructor (like it is done in the example that you linked).
Related
It is my understanding that I can test that a method call will occur if I call a higher level method, i.e.:
public abstract class SomeClass()
{
public void SomeMehod()
{
SomeOtherMethod();
}
internal abstract void SomeOtherMethod();
}
I want to test that if I call SomeMethod() then I expect that SomeOtherMethod() will be called.
Am I right in thinking this sort of test is available in a mocking framework?
You can see if a method in something you have mocked has been called by using Verify, e.g.:
static void Main(string[] args)
{
Mock<ITest> mock = new Mock<ITest>();
ClassBeingTested testedClass = new ClassBeingTested();
testedClass.WorkMethod(mock.Object);
mock.Verify(m => m.MethodToCheckIfCalled());
}
class ClassBeingTested
{
public void WorkMethod(ITest test)
{
//test.MethodToCheckIfCalled();
}
}
public interface ITest
{
void MethodToCheckIfCalled();
}
If the line is left commented it will throw a MockException when you call Verify. If it is uncommented it will pass.
No, mock testing assumes you are using certain testable design patterns, one of which is injection. In your case you would be testing SomeClass.SomeMethod and SomeOtherMethod must be implemented in another entity which needs to be interfaced.
Your Someclass constructor would look like New(ISomeOtherClass). Then you would mock the ISomeOtherClass and set expectation on its SomeOtherMethod to be called and verify the expectation.
Even though I agree that the #Paul's answer is the recommended way to go I just want to add one alternative way which is provided by moq off the self.
Since SomeClass is abstract it is indeed mockable, but public void SomeMehod() isn't. The point is to find the way to mock and somehow invoke that method and then using CallBase propagate the call to the SomeOtherMethod(). It might sound as a hack but it is simple in essence. It could be used in the case if the proposed refactoring is not possible.
// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass
{
public virtual void DummyMethod() => base.SomeMethod();
}
Then you could setup DummyMethod() to propagate the call by setting CallBase flag.
//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();
//Act
mock.Object.SomeMethod();
//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);
Need to implement Moq Unit Test and Actual Unit Test in same test class , with help of some config file key.
Is it possible to do so using same object which will be assigned based on the config value ?
Means if config file key is "Moq" then Moq Unit Test will run and if not Actual Unit Test will run in same test class and in same method .
Yes you can, but likely it's not the best practice.
For example,
public class MyClass
{
IDependency _d;
public MyClass(IDependency d)
{
_d = d;
}
}
public class Dependency : IDependency
{
}
In the test class, I can have something like this:
[TestClass]
public class MyClassTests
{
MyClass _sut;
Mock<IDependency> _mockDependency;
Dependency _realDependency;
[TestInit]
public void Init()
{
var shouldUseMock = ConfigurationManager.AppSettings["key"];
if(shouldUseMock)
{
_mockDependency = new Mock<IDependency>();
_sut = new MyClass(_mockDependency.Object)
}
else
{
_realDependency = new Dependency();
_sut = new MyClass(_realDependency);
}
}
}
The problem will be setting up expectations based on different situations and it makes the test class much harder to maintain. You should rather create two tests, one real unit test with the mock and the other kind of integration test with real implementation.
I'm wondering if there is a way of setting up a mock for a dependency before the constructor of the System Under Test (SUT) is called when using a test case that sets up AutoData.
My SUT looks like:
class Sut
{
private readonly IFoo foo;
public Sut(IFooFactory factory)
{
this.foo = factory.Build(1, 2);
}
public IFoo Foo
{
get
{
return this.foo;
}
}
}
So the test that I'm writing looks like:
[Theory]
[AutoData]
internal void Foo_IsCorrectlySet_Test(
[Frozen] Mock<IFooFactory> fooFactory,
IFoo foo,
Sut sut)
{
fooFactory.Setup(mock => mock.Build(1, 2))
.Returns(foo)
.Verifiable();
var actual = sut.Foo;
Assert.Equal(foo, sut);
fooFactory.Verify();
}
Obviously this test fails as the constructor to the Sut runs before I am able to setup the IFooFactory. So I thought that I may have been able to change the declaration of the Sut to Lazy<Sut> in the test.
But again the constructor is still run before the actual test code is run meaning that my test is going to fail.
Now I know that I could easily setup this test with an actual Fixture object and create all of my objects manually and setting them up before I call to create the Sut which is fine but I'm wanting to keep my tests all roughly the same therefore I'm wondering if there is a way that I could still setup my test with the AutoData attribute but not run the constructor until after everything is setup?
AutoFixture was originally build as a tool for Test-Driven Development (TDD), and TDD is all about feedback. In the spirit of GOOS, you should listen to your tests. If the tests are hard to write, you should consider your API design. AutoFixture tends to amplify that sort of feedback, which may also be the case here.
Consider the invariants of the Sut class. Since it has a read-only IFoo class field, I'd interpret this as a strong indication that IFoo is a dependency of the class.
If that's the case, then inject IFoo via the constructor, instead of IFooFactory:
public class Sut
{
private readonly IFoo foo;
public Sut(IFoo foo)
{
this.foo = foo;
}
public IFoo Foo
{
get { return this.foo; }
}
}
You can still compose it using IFooFactory in the application's Composition Root:
var sut = new Sut(aFactory.Build(1, 2));
This will make the tests easier to write. I can't even show you how the above test would look with this refactoring, because it'd be redundant and can (and should) be deleted.
FWIW, the original design proposed above violates Nikola Malovic's 4th law of IoC that constructors should do no work.
You can use the Fixture object pattern.
This allows you to setup your mocks before creating the sut.
Something in the lines of:
private class Fixture
{
public Mock<FooFactory> FooFactoryMock { get; set; } = new Mock<FooFactory>();
public Sut GetSut()
{
return new Sut(FooFactoryMock.Object);
}
}
[Theory]
[AutoData]
internal void Foo_IsCorrectlySet_Test(
IFoo foo)
{
var fixture = new Fixture();
fixture.FooFactory.Setup(mock => mock.Build(1, 2))
.Returns(foo)
.Verifiable();
var sut = fixture.GetSut();
var actual = sut.Foo;
Assert.Equal(foo, sut);
fooFactory.Verify();
}
You can use [Frozen] Attribute to freeze Moq dependency or try out write your own [CustomAttribute] to control dependencies.
I currently have a base service class that all my services extend. This is what one of the methods look like:
protected internal virtual T PerformServiceOperationWithExceptionHandling<T>(Func<T> func)
{
try
{
return func.Invoke();
}
...
}
In the derived classes I call the method like this:
public AddGuestResponse AddGuest(AddGuestRequest addGuestRequest)
{
return PerformServiceOperationWithExceptionHandling(() => AddGuestLogic(addGuestRequest));
}
I want to test AddGuest and ensure "AddGuestLogic" is being passed as a parameter in the base method? How do I achieve this with nSubstitute and nUnit. I don't think its possible?
================================================
I ended up using the following code:
[Test]
public void AddGuest_WhenCalled_PerformsAddGuestLogicWithExceptionHandling()
{
Func<AddGuestResponse> addGuestLogic = null;
_guestService.PerformServiceOperationWithExceptionHandling(Arg.Do<Func<AddGuestResponse>>(arg => addGuestLogic = arg));
var addGuestRequest = new AddGuestRequest();
_guestService.AddGuest(addGuestRequest);
_guestService.ClearReceivedCalls();
addGuestLogic.Invoke();
_guestService.Received().AddGuestLogic(addGuestRequest);
}
The _guestService is created in my setup method as follows: Substitute.ForPartsOf();
I second Sunny Milenov's answer, but would go one step further by advising you to change your design. I have learned the hard way that many of these headaches with testing base class behavior go away when you follow the principle of composition over inheritance.
I.e., if you refactor your base class to a collaborator, which you inject into your services' constructor, you can test that in isolation and mock it in your services' tests. No worrying about testing an abstract base class or testing the same exception handling in all of your services' tests.
You would test that the collaborator correctly invokes the func in the collaborator's tests.
In the services' tests you can just mock the collaborator to return the Func's result right away:
[Test]
public void ServiceLogicIsExecuted()
{
var collaborator = Substitute.For<ICollaborator>();
//Tell the test double to return the Func's result. You'd probably want to do this in the setup method.
collaborator.PerformServiceOperation(Arg.Any<Func<int>>()).Returns(x => ((Func<int>)x[0]).Invoke());
var sut = new Service(collaborator);
var result = sut.CalculateSomething();
Assert.That(result, Is.EqualTo(99));
}
public class Service
{
private readonly ICollaborator _collaborator;
public Service(ICollaborator collaborator)
{
_collaborator = collaborator;
}
public int CalculateSomething()
{
return _collaborator.PerformServiceOperation(ExecuteLogic);
}
private static int ExecuteLogic()
{
return 99;
}
}
public interface ICollaborator
{
T PerformServiceOperation<T>(Func<T> func);
}
Short answer - you shouldn't. Unit testing is about testing the behavior of the tested method, not the implementation details.
Long answer:
It doesn't matter how the class internally works, as far as it produces the expected results.
You need to test your public method on the final class and see if this works as expected. Testing a base/abstract class in isolation proves nothing.
Typically when I need to mock out a class for testing, I'll use a library such as Rhino Mocks. Here I have a class called MyService that expects a IEmailSender.
public class MyService
{
private readonly IEmailSender sender;
public MyService(IEmailSender sender)
{
this.sender = sender;
}
public void Start()
{
this.sender.SendEmail();
}
}
If I needed to test the interaction between these two objects, my test would look something like this:
[TestMethod]
public void Start_Test_Using_Rhino_Mocks()
{
IEmailSender emailSender = MockRepository.GenerateMock<IEmailSender>();
MyService service = new MyService(emailSender);
service.Start();
emailSender.AssertWasCalled
(
x => x.SendEmail(),
c => c.Repeat.Once()
);
}
In the test above, I'm using Rhino Mocks to generate the mock and assert that the SendEmail() method was called once.
But what if I could not use Rhino Mocks and had to create manual mocks?
public class MockEmailSender : IEmailSender
{
public void SendEmail()
{
}
}
[TestMethod]
public void Start_Test_Using_Manual_Mocks()
{
MockEmailSender emailSender = new MockEmailSender();
MyService service = new MyService(emailSender);
service.Start();
// How do I test the interaction?
}
With the mock that I created manually, how would I verify that the SendEmail() method was called? I could put my assertions in the SendEmail() method of the mock, but that would make the test hard to understand since I don't immediately see what's going on when I look at the test.
A very simple solution would have your manual mock just be a stateholder, with counters for the calls to each method. But it's fragile ...
public class MockEmailSender : IEmailSender
{
public int SendCount = 0;
public void SendMail(...)
{
SendCount++;
}
// ... other IEmailSender methods ...
}
Then just query SendCount after making your method call, and making sure that it's == 1.
Remember, Rhino Mocks is creating this dynamically for you -- if you do it manually you have to react to interface changes before compile time, by hand.
I think that you have no other option than setting a flag in "SendEmail()", and checking that flag from the test throgh a new method of MockEmailSender like "sendMailWasInvoked()" or something like this (which is in fact a kind of "verify").
You can extend this to count the number of invokations, parameters...
well i would advise against creating any manual Mocks (because if you add new method to interface, it gets broken).
if you really have to do it, when expose some counter/bool in your MockEmailSender and you can Assert it later on.
Assert.IsTrue(emailSender.IsCalled)