'Mocking IEnumerable<T> for each class that implements <T> using Moq
I have the following interface
public interface ICommand<TResult, TModel>
{
Task<TResult> DoWorkAsync(TModel model);
}
Which is implemented by one or more such Command classes:
public class MyCommand1 : ICommand<Response, Model>()
{
public async Task<Response> DoWorkAsync(Model model) {
// do something
}
}
public class MyCommand2 : ICommand<Response, Model>()
{
public async Task<Response> DoWorkAsync(Model model) {
// do something else
}
}
The Respose and Model classes are as follows:
public class Response
{
public bool IsSuccessful {get;set;}
}
public class Model
{
public Guid Id {get;set;}
public string Name {get;set;}
}
Then I have an orchestrator class that has a dependency on an IEnumerable of IEnumerable<ICommand<Response, Model>>
public class MyOrchestrator
{
private readonly IEnumerable<ICommand<Response, Model>> _commands;
public MyOrchestrator(IEnumerable<ICommand<Response, Model>> commands)
{
_commands = commands;
}
public async Task ExecuteAsync(Model model)
{
myCommand1_Response = await _commands
.OfType<MyCommand1>()
.First()
.DoWorkAsync(model);
myCommand2_Response = await _commands
.OfType<MyCommand2>()
.First()
.DoWorkAsync(model);
// other operations
}
}
Now in my test I'm trying to mock the MyOrchestrator class's dependency IEnumerable<ICommand<Response, Model>> for each of the MyCommand types. How can I achieve this?
Solution 1:[1]
The problem is that MyCommand2 and MyCommand1 are concrete classes. You'll either need to make them be IMyCommand1 and IMyCommand2 or make DoWorkAsync virtual.
Solution 2:[2]
I think you could simplify your orchestator which would make mocking trivial.
public class MyOrchestrator
{
...
public MyOrchestrator(ICommand<Response, Model> command1, ICommand<Response, Model> command2)
{
this.command1 = command1 ?? throw...;
this.command2 = command2 ?? throw...;
}
public async Task ExecuteAsync(Model model)
{
myCommand1_Response = await command1.DoWorkAsync(model);
myCommand2_Response = await command1.DoWorkAsync(model);
// other operations
}
}
Now mocking this is nothing special.
var mockCommand1 = new Mock<ICommand<Response, Model>>(MockBehaviour.Strict);
...
var tested = new MyOrchestrator(command1: mockCommand1.Object, ...);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | tymtam |
| Solution 2 | tymtam |
