C Sharp - Mock

MOCK

Mock objects are used when you are setting up automated testing. In theory these objects are like your normal API objects however they do not normally write to your database.

So if you had a bulletin class in the interface, you might also have a bulletinMock object.

Your bulletin class would contain methods like GetAllBulletins, Get1, Append, Update, and Delete. These methods would perform actual database updates.

Your bulletinMock class would contain the same methods, but they may just update data in memory.

When you execute your automated testing, you will want it to execute against the Mock objects.

A complexity is how do you manipulate your API so that your program calls business objects, but your test scripts use the mock objects?

If you consider an onion framework. A note class. It might have 4 layers.
1 - domain
2 - application
3 - infrastructures
4 - API

Generally speaking layer 4 might contain pointers to layer 3, 2, 1. Layer 3 might contain pointers to layer 2, 1, layer 2 might contain references to 1.

The API’s might call services located in the application layer.

If you were testing your API layer, you might create a mock object for the services layer.

The Note Service layer has the following interface:

1
2
3
4
5
6
7
8
9
10
11
namespace Note.Application.Services
{
public interface INoteService
{
Task<IResult<List<NoteDto>>> GetAllNotesAsync(string companyKey, string applicationKey, string applicationSubKey);
Task<IResult<NoteDto>> GetNoteById(string companyKey, long id);
Task<IBaseResult> CreateNote(NoteDto noteDto);
Task<IBaseResult> UpdateNote(NoteDto noteDto);
Task<IBaseResult> DeleteNote(string companyKey, long id);
}
}

Here is a of the mock NoteService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class NoteControllerTests
{
private NoteController _controller;
private Mock<INoteService> _mockNoteService;
private NoteValidator validator;
private readonly IMapper _mapper;

[TestInitialize]
public void Setup()
{
// Arrange
var noteDtoList = new List<NoteDto>
{
new NoteDto { ApplicationKey = "MyApp",
ApplicationSubKey = "Notes",
CompanyKey = "Test",
Note = "This is a new note - 1",
Who = "John Doe" },
new NoteDto { ApplicationKey = "MyApp",
ApplicationSubKey = "Notes",
CompanyKey = "Test",
Note = "This is a new note 2",
Who = "John Doe" },
// Add more NoteDto instances as needed
};

var noteDto = new NoteDto
{
ApplicationKey = "MyApp",
ApplicationSubKey = "Notes",
CompanyKey = "Test",
Note = "This is a new note - 1",
Who = "John Doe"
};

var result = new Result<List<NoteDto>>(noteDtoList);
result.WasSuccessful = true;

_mockNoteService = new Mock<INoteService>();
_mockNoteService
.Setup(service => service.GetAllNotesAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(result);

var result2 = new Result<NoteDto>(noteDto);
result2.WasSuccessful = (noteDto.CompanyKey == "" | noteDto.ApplicationKey == "" ? false : true);

// mock the GetNoteById method
_mockNoteService
.Setup(service => service.GetNoteById(It.IsAny<string>(), It.IsAny<long>()))
.ReturnsAsync(result2);

// mock the CreateNote method
_mockNoteService
.Setup(service => service.CreateNote(It.IsAny<NoteDto>()))
.ReturnsAsync(result2);

// mock the UpdateNote method
_mockNoteService
.Setup(service => service.UpdateNote(It.IsAny<NoteDto>()))
.ReturnsAsync(result2);

// mock the DeleteNote method
_mockNoteService
.Setup(service => service.DeleteNote(It.IsAny<string>(), It.IsAny<long>()))
.ReturnsAsync(new Result());

_controller = new NoteController(_mockNoteService.Object);

// fluent validation
validator = new NoteValidator();

}

If you look at the Setup() method, you see a very version one of the NoteService mock object.

You’ll notice a couple of things

  • We create a noteDtoList array - this will be a sample results of the GetAllData method.

  • You see a noteDto object - which is sample results of a GetData method.

  • I create a Mock object of type INoteService, then I setup methods using the .Setup().ReturnsAsync(r) pairs

  • The interface of the first method GetAllNotesAsync has several parameters, so our setup method creates placeholders for each of those parameters.

  • We declare a _controller variable. This is a pointer to the note controller. Then we inject the MockNoteService object into that. Then we can use the _controller variable in the rest of the class method.