I have to test a projection that handle a given events and persist it on a read only Mongo database (I'm using official c# Mongo Driver):
public class MyObjectProjection : IHandleMessages<RegisteredEvent>
{
private MongoCollection<MyObjectView> _collection;
private MyObjectView item;
public MyObjectProjection (MongoDatabase db)
{
_collection = db.GetCollection<MyObjectView>("my-object");
}
public void Handle(RegisteredEvent message)
{
item = new MyObjectView();
item.Id = message.Id;
// some code omitted
_collection.Save(item);
}
}
I need to unit test the Handle method, given that:
I don't want an integration test. Database and collection are mocked, so the save is not real
I just want to test the item-message mapping
the members are hidden and I don't want to make them more visibile
Should I use alternative solution rather than reflection or friendly assembly? What is the best practice in a case like this?
Right now my test look like this:
[TestMethod]
public void TestMethod1()
{
// ARRANGE - some code omitted
databaseMock
.Setup(x => x.GetCollection<MyObjectView>(It.IsAny<string>()))
.Returns(collection);
collectionMock
.Setup(x => x.Save(It.IsAny<MyObjectView>()))
.Returns(It.IsAny<WriteConcernResult>);
// ACT
var handler = new MyObjectProjection(database);
handler.Handle(evt);
// ASSERT
// nothin' to assert here!
}
this works, but i have nothing to assert when Handle method is completed.
What is the best practice in a case like this?
The best practice is to make members visible. Is there any particular reason why you need to hide members?
Then, you can assert against argument passed to Save method :
MyObjectView objectView;
collectionMock
.Setup(x => x.Save(It.IsAny<MyObjectView>()))
.Callback<MyObjectView>((obj) => objectView= obj)
.Returns(It.IsAny<WriteConcernResult>);
Assert.That(objectView.Id, Is.EqualTo(evt.Id));
//assert other properties
Well, your Handle() method interacts with the collection, by calling the Save() method. Therefore you can expect that the element passed to the Handle method has proper ID set:
collectionMock.Verify(x=>x.Save(It.Is<MyObjectView>(v => v.Id == 5)), Times.Once,"save should be called with object with Id = 5");
I assumed here that the evt that is passed into Handle() has and Id of 5. Code not tested, but I think something like that would do the trick.
Related
In my .Net6 web app, I attempted to register service injection for 2 implementations of a single IWordRepository Interface:
WordRepositoryInMemory, working with in-memory data;
WordRepositoryDatabase with calls to the database;
Following the example set out in this article, I created an enum:
public enum WordRepositoryImplementation
{
WordRepositoryInMemory,
WordRepositoryDatabase
}
Then, in my Program.cs, I registered the two services:
builder.Services.AddScoped<WordRepositoryDatabase>();
builder.Services.AddScoped<WordRepositoryInMemory>();
builder.Services.AddTransient<Func<WordRepositoryImplementation, IWordRepository?>>(wordRepositoryProvider => key =>
{
return key switch
{
WordRepositoryImplementation.WordRepositoryInMemory => wordRepositoryProvider.GetService<WordRepositoryInMemory>(),
WordRepositoryImplementation.WordRepositoryDatabase => wordRepositoryProvider.GetService<WordRepositoryDatabase>(),
_ => null,
};
});
Then, I called it in my controller like so:
private readonly IWordRepository _wordRepositoryDatabase; // I only require one of the implementations to be called by this controller.
public DictionaryDataController(Func<WordRepositoryImplementation, IWordRepository> serviceResolver)
{
_wordRepositoryDatabase = serviceResolver(WordRepositoryImplementation.WordRepositoryDatabase);
}
Unfortunately, this added complexity messed up my tests for the controller. I am no longer able to instantiate the sut with a simple Mock.Object of the WordRepositoryDatabase service. By saying unable, I mean that I don't quite have the required experience handling delegates, yet.
In my test fixture, I tried to replace the original mock implementation of the service:
private Mock<IWordRepository> _wordRepository;
// ....
_wordRepository= new Mock<IWordRepository>();
// ....
DictionaryDataController sut = new(_wordRepositoryDatabase.Object);
To something that returns a Mock of the IWordRepository, so that I could use it in my constructor:
private Func<WordRepositoryImplementation, IWordRepository?> _funcWordRepositoryImplementation;
// ...
// ...
DictionaryDataController sut = new(_funcWordRepositoryImplementation);
However, I cannot grasp the required syntax here. The closest I got to was a parameterless Func<>() that returned the Mock.Object, but it was clearly missing something.
_funcWordRepositoryImplementation= () =>
{
return new Mock<WordRepositoryImplementation, IWordRepository>();
};
And attempts to pass some arguments to it caused their own set of errors.
What would the correct way to set up this field be?
Just use lambda expression with discard parameter which will return _wordRepositoryDatabase.Object:
DictionaryDataController sut = new(_ => _wordRepositoryDatabase.Object);
I'm trying to use FakeItEasy (version 4.9.1) to create unit tests for some legacy code. I've created two unit tests, one of which works just as expected, and one very similar which doesn't work despite lots of trial and error.
Here's an excerpt from the method that seems impossible to test:
public class PosMessageProcessor : IPosMessageProcessor
{
public void Execute()
{
PurchaseOrderRepository repo = new PurchaseOrderRepository();
...
try
{
m_PurchaseOrder = GetOrderForProcessing(repo);
...
And here's my test:
[TestMethod]
[TestCategory("POS")]
public void ExecuteTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
IPosMessageProcessor fakePosMessageProcessor = A.Fake<IPosMessageProcessor>();
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).Returns(purchaseOrder);
// Act
_posMessageProcessor.Execute();
// Assert
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).MustHaveHappened();
}
The _posMessageProcessor variable is an instance of the PosMessageProcessor class. I want to catch the call to the GetOrderForProcessing() method (within the Execute() method) and make it return my hard-coded purchaseOrder object. But I get another return value (null) instead. Why?
The unit test that works tests the GetOrderForProcessing() method:
[TestMethod]
[TestCategory("POS")]
public void GetOrderForProcessingTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
IPurchaseOrderRepository fakePurchaseOrderRepository = A.Fake<IPurchaseOrderRepository>();
A.CallTo(() => fakePurchaseOrderRepository.GetPurchaseOrderByOrderTrackingNumber(A<string>.Ignored)).Returns(purchaseOrder);
// Act
PurchaseOrder result = _posMessageProcessor.GetOrderForProcessing(fakePurchaseOrderRepository);
// Assert
A.CallTo(() => fakePurchaseOrderRepository.GetPurchaseOrderByOrderTrackingNumber(A<string>.Ignored)).MustHaveHappened();
Assert.IsNotNull(result);
}
In this case, the call to GetPurchaseOrderByOrderTrackingNumber() returns my hard-coded object as expected. The two tests are virtually the same, except that the GetOrderForProcessing() method takes a parameter while Execute() does not.
ExecuteTest is failing because you configure a fake IPosMessageProcessor and then call Execute on a real PosMessageProcessor, _posMessageProcessor. _posMessageProcessor, being an actual PosMessageProcessor, executes its regular code path, calling the actual Execute, which will call the actual GetOrderForProcessing.
(Note that you can actually delete the fakePosMessageProcessor variable and all references to it from your test, and the behaviour will be the same.)
I do not recommend this kind of testing, but in order to fake GetOrderForProcessing and still test the actual Execute code, you would have to write a test like
public void NewExecuteTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
// Get a fake PosMessageProcessor that falls back to original behaviour for all calls.
IPosMessageProcessor fakePosMessageProcessor = A.Fake<PosMessageProcessor>(options => options.CallsBaseMethods());
// Now fake out the GetOrderForProcessing call so we can test Execute.
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).Returns(purchaseOrder);
// Act
fakePosMessageProcessor.Execute();
// Assert
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).MustHaveHappened();
}
I'm mocking a DbContext and its DbSets as described here.
I'd like to create a utility method for creating my mock DbContexts, which sets up each of the context's DbSets to return an empty list by default (otherwise I get errors about null references whenever I try to query one of the DbSets). Then in unit tests where I want non-empty data in a certain DbSet, I want to call Setup again on that DbSet to supply that value than I want returned. Code is below.
I did this in a unit test and it appears to be working, but I can't find anything about how Moq handles calling Setup twice on the same property. Is doing this OK, or will it have unexpected side effects? Using the debugger, I looked into context.Setups, and calling Setup a second time on the same property adds a second object to Setups rather than overwriting the first one, which worries me.
[TestClass]
public class MyTests
{
// Creates a new Mock<MyContext> and calls Setup on each property so
// that they all return empty lists
private Mock<MyContext> CreateContext()
{
Mock<MyContext> context = new Mock<MyContext>();
// CreateMockDbSet is a utility method which creates a Mock<DbSet<TEntity>>
// as described in the MSDN article listed above
context.Setup(e => e.Customers).Returns(CreateMockDbSet<Customer>().Object);
context.Setup(e => e.Orders).Returns(CreateMockDbSet<Order>().Object);
return context;
}
[TestMethod]
public void MyTest()
{
// By default, context.Customers and context.Orders will both return
// empty DbSets
Mock<MyContext> context = CreateContext();
List<Order> orders = new List<Order>
{
new Order { Id = 1 },
new Order { Id = 2 },
new Order { Id = 3 }
};
// CreateMockDbSet creates a Mock<DbSet<Order>> which returns the orders
// in 'orders'. What does Moq do when I call Setup again on 'Orders'?
context.Setup(e => e.Orders).Returns(CreateMockDbSet(orders).Object);
// ... Do test ...
}
}
https://msdn.microsoft.com/en-us/library/dn314429(v=vs.113).aspx
If you create a subsequent setup on a method and it's non-conditional (no constraints on the arguments) then it removes all previous setups for the method.
In your case where you don't have a method accepting arguments then you obviously can't add any constraints on them, so your subsequent setup will just replace the previous.
See this answer for an explanation of the source code.
I'm using FakeItEasy to do some testing, but I have run into a problem.
When testing that the expected data is sent to a faked service, I would like to be able to see the error data as well.
Right now I only see that the call never happened.
Maybe I'm setting it up all wrong, but then I'd like some hints on how to correct it. :)
My case is:
A call to the same service twice, with different values.
I want separate tests to verify each call.
If any of the parameters, doesn't have the expected value, I would like to get an error message stating that. Similar to when you do an Assert.AreEqual().
Right now I only get "Call did not happen", which is totally understandable, because I realise that is what I'm testing. But I would like to be able to verify that a specific call has only been made once, and if it did not happen I would like to see which values were used to not make it happen.
I used this solution: http://thorarin.net/blog/post/2014/09/18/capturing-method-arguments-on-your-fakes-using-fakeiteasy.aspx
when I only had one call, but with two calls it doesn't work.
[TestFixture]
public class TestClass
{
[Test]
public void TestOne()
{
// Arrange
var fake = A.Fake<IBarservice>();
var a = new Foo(fake);
// Act
a.DoStuff(1);
//Assert
A.CallTo(() => fake.DoOtherStuff(A<int>.That.Matches(x => x == 2))).MustHaveHappened(Repeated.Exactly.Once);
}
[Test]
public void TestTwo()
{
// Arrange
var fake = A.Fake<IBarservice>();
var a = new Foo(fake);
// Act
a.DoStuff(1);
//Assert
A.CallTo(() => fake.DoOtherStuff(A<int>.That.Matches(x => x == 3))).MustHaveHappened(Repeated.Exactly.Once);
}
}
public class Foo
{
private readonly IBarservice _barservice;
public Foo(IBarservice barservice)
{
_barservice = barservice;
}
public void DoStuff(int someInt)
{
someInt++;
_barservice.DoOtherStuff(someInt);
// I should have increased someInt here again, but this is a bug that my tests catches
_barservice.DoOtherStuff(someInt);
}
}
public interface IBarservice
{
void DoOtherStuff(int someInt);
}
Markus, I had a comment that I've redacted, since I made an error.
You say you only get "Call did not happen" and
… I would like to be able to verify that a specific call has only been made once, and if it did not happen I would like to see which values were used to not make it happen.
I fear I don't understand what information you were hoping for, since when I run TestOne, I get
FakeItEasy.ExpectationException
Assertion failed for the following call:
FakeItEasyQuestionsVS2015.IBarservice.DoOtherStuff(<x => (x == 2)>)
Expected to find it exactly once but found it #2 times among the calls:
1: FakeItEasyQuestionsVS2015.IBarservice.DoOtherStuff(someInt: 2) repeated 2 times
...
This says that the call DoOtherStuff was made twice, with someInt passed in as the value 2 each time.
I'm just starting out with BDD/TDD using MSpec (with AutoMocking by James Broome) and RhinoMocks. Here's an excerpt from my practice project:
namespace Tests.VideoStore.Controllers
{
public abstract class context_for_movie_controller :
Specification<MovieController>
{
private static IList<Movie> movies;
protected static IMovieRepository _movieRepository;
protected static ActionResult _result;
protected static string title;
protected static string director;
Establish context = () =>
{
_movieRepository = DependencyOf<IMovieRepository>();
};
}
[Subject(typeof(MovieController))]
public class when_searching_for_movies_with_director :
context_for_movie_controller
{
Establish context = () =>
{
title = null;
director = "James Cameron";
var movie4 = new Movie {
Title = "Terminator", Director = "James Cameron"};
var movie6 = new Movie {
Title = "Avatar", Director = "James Cameron"};
movies = new List<Movie> {movie4, movie6};
// Repository returns all movies.
_movieRepository.Stub(x => x.FindMovies(title, director))
.Return(movies);
};
Because of = () => _result = subject.Find(title, director);
It should_fetch_movies_from_the_repository = () =>
_movieRepository.AssertWasCalled(x =>
x.FindMovies(title, director));
It should_return_a_list_of_movies_matching_the_director = () =>
_result.ShouldBeAView().And()
.ShouldHaveModelOfType<IEnumerable<Movie>>)
.And().ShouldContainOnly(movies);
}
As you can see, I stubbed out the FindMovies() method on the MovieRepository class. Then I'm calling the MoviesController.Find() action. My question is, should there be an assert to check if the stubbed method (FindMovies) was called by the controller? Or perhaps should I only care about the returned result and not where it was taken from? Furthermore, a spec that says "should_fetch_movies_from_the_repository" looks a lot like an engineering task, not something that a client might understand - does it have its place in BDD?
the general rule to follow for assertions is that you assert against output interactions, not input interactions.
the FindMovies stub is returning a "movies" collection to the class that called it and you are then verifying that the class received the correct list via the "it should return a list of movies matching the director" assertion. if the FindMovies method is not called, then this assertion will fail.
therefore, you do not need to assert the calls against the FindMovies method.
to counterpoint this, if you have an mock or stub that is purely output - let's say an IView interface being called by a Presenter class, then you do want to assert against the IView being called. for example, this code:
public class MyPresenter
{
... other code here
public DoSomething()
{
IList data = GetSomeData();
myView.DisplayData(data);
}
}
you would want to assert that the view.DisplayData method is called in this case, because you are not retrieving anything from this call that can be asserted by another test.
as for the "fetch from repository" - of course your customers care about that. they want the system to save movies to the storage and load them from the storage. however ... the FindMovies call is an input into the class being tested, so it's not necessary to have this assetion or test, at all. if the FindMovies method is not called, then the other test will fail and let you know that there is a problem.