I'm hitting a bit of a chicken and egg problem setting up my mocks for Reactive Extensions code in a constructor. Here's the class under test (along with the service interface it depends on):
class MyViewModel
{
public int Thing { get; set; }
public MyViewModel(IMyService service)
{
service.StreamOfThings.Subscribe(x => Thing = x));
}
public void SomeClickEvent()
{
// Do something with `Thing`
}
}
public interface IMyService
{
IObservable<int> StreamOfThings { get; }
}
To make testing easier, I have also defined a custom attribute named AutoMockData I can use to use Moq to inject mock instances into my classes through AutoFixture:
public class AutoMockDataAttribute : AutoDataAttribute
{
private static IFixture Create() =>
new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
public AutoMockDataAttribute() : base(Create) {}
}
With this, I am ready to write my test (using NUnit3):
[Test, AutoMockData]
public void Verify_some_behavior(
[Frozen] Mock<IMyService> mockService,
MyViewModel vm)
{
mockService.Setup(x => x.StreamOfThings).Returns(Observable.Return(100));
vm.SomeClickEvent();
vm.Thing.Should().Be(100);
}
This test fails. I believe this fails because the constructor of MyViewModel sets up an observable pipeline on a different instance of IObservable than the one I set up in the unit test method.
The ideal solution here would be to use the IObservable<> instance that was set up using AutoFixture, but I'm not sure how to best do that. It would somehow need to already set up a pre-constructed pipeline for me.
The workaround I have found is to not use the AutoMock functionality of AutoFixture and instead construct a Fixture directly and directly use the .Freeze() and .Create() methods in the proper order. However, this leads to an arguably more difficult to read and less clean unit test body.
How can I continue to implement my test as shown here but also be able to set up any observables before they are used in the SUT's constructor?
I think the issue here is that you never actually exercise the observable, so Thing keeps the value that AutoFixture assigned it on creation.
In the example below the Subject is frozen as an IObservable<int> which is then resolved as the return value for the StreamOfThings. Then the subject is forced to trigger the subscribers.
[Test, AutoMockData]
public void Verify_some_behavior(
[Frozen(Matching.ImplementedInterfaces)] Subject<int> observable,
MyViewModel vm)
{
observable.OnNext(100);
vm.SomeClickEvent();
vm.Thing.Should().Be(100);
}
The example is equivalent to the following:
[Test, AutoMockData]
public void Verify_some_behavior(
Subject<int> observable,
[Frozen] Mock<IMyService> mockService,
MyViewModel vm)
{
mockService.Setup(x => x.StreamOfThings).Returns(observable);
observable.OnNext(100);
vm.SomeClickEvent();
vm.Thing.Should().Be(100);
}
This way of writing the test should also make it obvious how to handle multiple observable properties.
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);
I have a base class:
public abstract class MyBaseClass
{
protected virtual void Method1()
{
}
}
and a derived class:
public class MyDerivedClass : MyBaseClass
{
public void Method2()
{
base.Method1();
}
}
I want to write a unit test for Method2 to verify that it calls Method1 on the base class. I'm using Moq as my mocking library. Is this possible?
I came across a related SO link:
Mocking a base class method call with Moq
in which the 2nd answer suggests it can be achieved by setting CallBase property to true on the mock object. However it's not clear how this would enable the call to the base class method (Method1 in the above example) to be verified.
Appreciate any assistance with this.
Unit tests should verify behavior, not implementation. There are several reasons for this:
The results are the goal, not how you get the results
Testing results allows you to improve the implementation without re-writing your tests
Implementations are harder to mock
You might be able to put in hooks or create mocks that verify that the base method was called, but do you really care how the answer was achieved, or do you care that the answer is right?
If the particular implementation you require has side effects that you can verify, then that is what you should be validating.
Mocking the base class from the perspective of the derived class is not possible. In your simple example, I would suggest one of the two options.
Option 1: In the event that MyDerivedClass really shouldn't care what MyBaseClass is up to, then use dependency injection! Yay abstraction!
public class MyClass
{
private readonly IUsedToBeBaseClass myDependency;
public MyClass(IUsedToBeBaseClass myDependency){
_myDependency = myDependency;
}
public void Method2()
{
_myDependency.Method1();
}
}
Elsewhere in test land...
[TestClass]
public class TestMyDependency {
[TestMethod]
public void TestThatMyDependencyIsCalled() {
var dependency = new Mock<IUsedToBeBaseClass>();
var unitUnderTest = new MyClass(dependency.Object);
var unitUnderTest.Method2();
dependency.Verify(x => x.Method1(), Times.Once);
}
}
Option 2: In the event that MyDerivedClass NEEDS to know what MyBaseClass is doing, then test that MyBaseClass is doing the right thing.
In alternative test land...
[TestClass]
public class TestMyDependency {
[TestMethod]
public void TestThatMyDependencyIsCalled() {
var unitUnderTest = new MyDerivedClass();
var unitUnderTest.Method2();
/* verify base class behavior #1 inside Method1() */
/* verify base class behavior #2 inside Method1() */
/* ... */
}
}
What you're describing is not a test of your code, but a test of the behavior of the language. That's fine, because it's a good way to ensure that the language behaves the way we think it does. I used to write lots of little console apps when I was learning. I wish I'd known about unit testing then because it's a better way to go about it.
But once you've tested it and confirmed that the language behaves the way you expect, I wouldn't keep writing tests for that. You can just test the behavior of your code.
Here's a real simple example:
public class TheBaseClass
{
public readonly List<string> Output = new List<string>();
public virtual void WriteToOutput()
{
Output.Add("TheBaseClass");
}
}
public class TheDerivedClass : TheBaseClass
{
public override void WriteToOutput()
{
Output.Add("TheDerivedClass");
base.WriteToOutput();
}
}
Unit test
[TestMethod]
public void EnsureDerivedClassCallsBaseClass()
{
var testSubject = new TheDerivedClass();
testSubject.WriteToOutput();
Assert.IsTrue(testSubject.Output.Contains("TheBaseClass"));
}
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)