'Including an event-based model in a unit test
I'm new to C# and .NET development and I'm testing out a method from ThingEventService.cs.
ThingUpdatedEvent.cs is included in the service file and I'm trying to include it in the test, but I'm having trouble with 1. Ensuring that it's recognized by the test, and 2. Determining what I need to provide in order for it to be included properly.
I'm running into the following error:
Models/ThingUpdatedEvent.cs(12,15): error CS1729: 'object' does not contain a constructor that takes 3 arguments
, which is pointing to the : base() line that I've included in ThingUpdatedEvent.cs.
If I remove the following from the test:
ThingUpdatedEvent request = new ThingUpdatedEvent
(updateRequest, thingBeforeUpdate, thingAfterUpdate)
{
UpdateRequest = UpdateThingRequest,
ThingBeforeUpdate = ThingBeforeUpdate,
ThingAfterUpdate = ThingAfterUpdate
};
await this._svc.HandleThingUpdatedAsync(request);
then the test runs, but I'm getting a Moq.Mockexception error stating that it "Expected invocation on the mock once, but was 0 times". It's led me to think that I need to include ThingUpdatedEvent in order for the test to run and pass.
Questions:
- Do I need to include
ThingUpdatedEventin the test?- If not, what could be causing the invocation to not run?
- Is
:base ()allowed on event-based models?
ThingUpdatedEvent.cs
namespace someFolder.someOtherFolder.etc
{
public class ThingUpdatedEvent
{
public ThingUpdatedEvent(
[NotNull] UpdateThingRequest updateRequest,
[NotNull] Thing thingBeforeUpdate,
[NotNull] Thing thingAfterUpdate)
: base(updateRequest, thingBeforeUpdate, thingAfterUpdate) // is base:() necessary for this?
{
this.UpdateRequest = updateRequest;
this.ThingBeforeUpdate = thingBeforeUpdate;
this.ThingAfterUpdate = thingAfterUpdate;
}
[NotNull]
public UpdateThingRequest UpdateRequest { get; set; }
[NotNull]
public Thing ThingBeforeUpdate { get; set; }
[NotNull]
public Thing ThingAfterUpdate { get; set; }
}
}
ThingEventServiceTests.cs
public class ThingEventServiceTests
{
Mock<IAuditLog> _auditLog;
Mock<AuditHelper> _auditHelper;
ThingEventService _svc;
public ThingEventServiceTests()
{
this._auditLog = new Mock<IAuditLog>();
this._auditHelper = new Mock<AuditHelper>();
this._svc = new ThingEventService(
Mock.Of<IAEService>(),
this._auditLog.Object);
}
[Fact]
public async Task CanHandleThingUpdatedAsync()
{
var SourceEntities = new List<AEModel>
{
AETypes.System.Create("Things")
};
ThingUpdatedEvent request = new ThingUpdatedEvent
(updateRequest, thingBeforeUpdate, thingAfterUpdate)
{
UpdateRequest = UpdateThingRequest,
ThingBeforeUpdate = ThingBeforeUpdate,
ThingAfterUpdate = ThingAfterUpdate
};
await this._svc.HandleThingUpdatedAsync(request);
It.IsAny<IEnumerable<AEModel>>();
this._auditLog.Verify(m => m.RecordEventAsync(
"123435",
"requester",
SourceEntities,
AuditEventTypes.ThingEdited,
"Thing edited",
"Thing was edited: Some Title",
It.IsAny<IEnumerable<FieldChange>>(),
It.IsAny<IEnumerable<string>>(),
It.IsAny<IEnumerable<Tag>>(),
null,
null,
null
), Times.Once);
}
}
ThingEventService.cs
public async task HandleThingUpdatedAsync(ThingUpdatedEvent evt)
{
// if (condition)
{
IEnumerable<AEModel> defaultSourceEntities = await this._auditHelper
.GetDefaultSourceEntitiesForThingEventAsync(evt.ThingAfterUpdate);
Task auditLogEditTask = this._auditLog.RecordEventAsync(
id: evt.ThingAfterUpdate.Id.ToString(),
user: evt.UpdateRequest.Requester,
sourceEntities: defaultSourceEntities,
eventType: AuditEventTypes.ThingEdited,
title: "Thing edited",
description: $"Thing was edited: {evt.ThingAfterUpdate.Title} (ID: {evt.ThingAfterUpdate.Id})",
fieldChanges: fieldChanges,
comments: null,
tags: this._auditHelper.GetDefaultTagsForThing(evt.ThingAfterUpdate));
tasks.Add(auditLogEditTask);
}
}
Solution 1:[1]
Update: I was able to do
[Fact]
public async Task CanHandleThingUpdatedAsync()
{
UpdateThingRequest updateThingRequest = new UpdateThingRequest(
something: "something",
etc: "etc"
);
Thing thingBeforeUpdateRequest = new Thing
{
Name = "Paper Pusher"
};
Thing thingAfterUpdateRequest = new Thing
{
Name = "Paper Flinger"
};
ThingUpdatedEvent request = new ThingUpdatedEvent(updateThingRequest, thingBeforeUpdateRequest, thingAfterUpdateRequest);
await this._svc.HandleThingUpdatedAsync(request);
// etc
without having to update ThingUpdatedEvent.cs. Thanks @ralf for pointing out the issue with the base class and for steering me in the right direction.
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 | Bodrov |
