I'm trying to write a test for a service that uses IStringLocalizerFactory to translate strings. All of the translations are in a single Resource file. I cannot seem to get the Mock for it to work, as it always throws a NullReferenceException. When debugging, it shows that _localizer is null. When I remove the localizer logic completely, the test succeeds.
Code I'm trying to test:
private readonly IStringLocalizer _localizer;
public EventService(IEventRepository eventRepository, IMemberEventRepository memberEventRepository, IStringLocalizerFactory factory)
{
this._eventRepository = eventRepository;
this._memberEventRepository = memberEventRepository;
this._localizer = factory.Create(typeof(Resource));
}
public async Task CreateEventRegistrationAsync(MemberEvent entity)
{
if (await this._memberEventRepository.GetMemberEvent(entity.EventId, entity.MemberId) != null)
{
throw new ArgumentException(_localizer["This member already participates in this event."].Value);
}
await this._memberEventRepository.CreateAsync(entity);
}
My tests:
private Mock<IStringLocalizerFactory> _stringLocalizerFactoryMock = new Mock<IStringLocalizerFactory>();
public EventServiceTests()
{
_service = new EventService(_eventRepoMock.Object, _memberEventRepoMock.Object, _stringLocalizerFactoryMock.Object);
}
[Fact]
public async Task CreateEventRegistrationAsync_ShouldThrowArgumentException_WhenMemberAlreadyRegisteredForEvent()
{
int eventId = 456;
int memberId = 123;
_stringLocalizerFactoryMock.Setup(x => x.Create(typeof(Resource)))
.Returns(() => new StringLocalizer<Resource>(_stringLocalizerFactoryMock.Object));
MemberEvent registration = new MemberEvent
{
EventId = eventId,
MemberId = memberId
};
_memberEventRepoMock.Setup(x => x.GetMemberEvent(eventId, memberId))
.ReturnsAsync(registration);
await Assert.ThrowsAsync<ArgumentException>(async () => await _service.CreateEventRegistrationAsync(registration));
}
From examining the subject under test I see that
_localizer["This member already participates in this event."].Value
will throw a null exception because _localizer[...]
was not setup and thus fail when .Value
is invoked.
Consider mocking a IStringLocalizer<T>
so that it can be setup to behave as expected when the test is invoked.
//...
var localizer = new Mock<IStringLocalizer<Resource>>();
localizer
.Setup(_ => _[It.IsAny<string>()])
.Returns(string key => new LocalizedString(key, key));
_stringLocalizerFactoryMock
.Setup(_ => _.Create(It.IsAny<Type>()))
.Returns(() => localizer.Object));
//...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.