I'm trying to mock a third-party interface that I'm using (EventStore ClientAPI/IEventStoreConnection), in particular this method:
Task<StreamEventsSlice> ReadStreamEventsForwardAsync(string stream, long start, int count, bool resolveLinkTos, UserCredentials userCredentials = null);
The problem I'm having is that the return type StreamEventsSlice
has readonly
fields and an internal
constructor i.e.
public class StreamEventsSlice
{
public readonly string Stream;
//other similar fields
internal StreamEventsSlice(string stream) //missing other fields
{
Stream = stream;
}
}
In my test code I'm mocking the event store connection using Moq
, setting up the ReadStreamEventsForwardAsyncMethod
, and trying to set the return type like so:
var connection = new Mock<IEventStoreConnection>();
connection.Setup(s => s.ReadStreamEventsForwardAsync(It.IsAny<string>(), It.IsAny<long>(), It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<UserCredentials>())
.ReturnsAsync(new StreamsEventSlice { props here });
But I can't set the properties, or call the constructor instead of that (I only actually need to set two properties)
I've tried making a stub that extends the original class, and returning that instead. Although I can hide the readonly properties I get an error on the class saying 'StreamEventsSlice does not have a constructor that takes 0 arguments'. Giving it a constructor doesn't work as I can't call the base ctor since it's internal.
How can I mock a method on an interface, when I can't instantiate the return type?
@MindSwipe linked two good answers, unfortunately I couldn't use this one for constructing an object as one of the parameters for the constructor was also set to internal. Instead I had to use this method, and use their other suggestion to set the properties.
I kept most of mock setup code the same, other then adding and using the following method to instantiate StreamEventsSlice
internal StreamEventsSlice GetStreamEventSlice(ResolvedEvent[] events = null, bool isEndOfStream = true)
{
events = events ?? new ResolvedEvent[0];
var type = typeof(StreamEventsSlice);
var slice = (StreamEventsSlice) FormatterServices.GetUninitializedObject(type);
type.GetField("Events").SetValue(slice, events);
type.GetField("IsEndOfStream").SetValue(slice, isEndOfStream);
return slice;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With