How to unit test code that uses EventReadResult, ResolvedEvent, RecordedEvent, etc. which have only internal constructors

Hi.

We have a lot of code similar to this:

public MyClass(IEventStoreConnection eventStoreConnection)
{
EventStoreConnection = eventStoreConnection;
}
private readonly IEventStoreConnection EventStoreConnection;
private EventStoreStreamCatchUpSubscription Subscription;
public void StartSubscription()
{
var eventReadResult = EventStoreConnection.ReadEventAsync(“some_stream_snapshots”, -1, true).Result;
if (eventReadResult.Status == EventReadStatus.Success && eventReadResult.Event != null)
{
var snapshotEventData = eventReadResult.Event.Value;
var snapshot = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(snapshotEventData.Event.Data));
// Do things with snapshot
}
Subscription = EventStoreConnection.SubscribeToStreamFrom("$some_stream", latestSnapshottedEventSequenceNumber, true, OnEventAppeared, OnLiveProcessingStarted, OnSubscriptionDropped);
}

which we would like to unit test. In particular we would like to unit test our error handling (when eventReadResult.Status != EventReadStatus.Success) and the deserialization of the eventData.Event.Data.

Typically we would mock IEventStoreConnection and its ReadEventAsync method, injecting the results we want to test. However we cannot take this approach with GetEventStore because most (if not all) of the classes involved have an internal constructor, which prevents us from creating instances:

[Test]
public void Should_throw_if_cant_read_snapshots()
{
var eventStoreConnection = new Mock();
eventStoreConnection
.Setup(x => x.ReadEventAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()))
.Returns(() => Task.FromResult(new EventReadResult(/* Values we want to inject but we can’t because the constructor is internal*/)));
}
This is just an example and we’re facing the same issue with ResolvedEvent and RecordedEvent (to test the processing of events),

The only alternative we can think of is to create our own abstractions (and the corresponding Adapters) for IEventStoreConnection and all the other classes mentioned above, but that will force us to have more code to maintain and to create one or more additional objects for processing each event due to the required (and unnecessary?) mapping, putting more pressure on the GC.

I’d like to hear what’s the recommended approach and what are other people doing in order to unit test their code when it has dependencies on GetEventStore classes.

Thanks,

Rodolfo

You should be wrapping (and just passing forward the data in most
cases depending if you are using metadata). EG A projection generally
is not interested in ResolvedEvent it is interested in the
deserialized object of data.

On a side note ResovledEvent etc are stucts so you don't get GC
pressure from using them
https://github.com/EventStore/EventStore/blob/release-v3.5.0/src/EventStore.ClientAPI/ResolvedEvent.cs#L8
copying from resolvedevent to fooresolvedevent vs passing
resolvedevent have the same cost as they are passed by value.

Cheers,

Greg

Hi Greg and thanks for replying so quickly.

We do the mapping, i.e. our domain is not using ResolvedEvent, etc. This mapping is what the

// Do things with snapshot

does.

The problem is that we are struggling to unit test the mapping itself. How can we test the mapping (and error handling logic) when we can’t mock IEventStoreConnection and its methods? Code like this has to live somewhere and we’d like to test it:

What most people do is wrap the connection logic into a single object
(sometimes 1-2 more for subscriptions) then integration test those
objects against an embedded eventstore. Everything else is tested by
mocking etc their abstraction.

Cheers,

Greg

Thanks again.

How could I test arbitrary error conditions with the embedded EventStore? I haven’t seen anything indicating that I can force the embedded EventStore to issue errors, etc. How would I test my

“if (eventReadResult.Status != EventReadStatus.Success)”

branch of the code?

After looking at the source code it looks like making the constructors public would solve this issue and improve the testability of our code.

I’m happy to create the pull request myself but could someone from the team please let me know if it has any chance to be approved? Do you think having them as internal is important to your design, or is it just a default that you would be happy to change?

Cheers,

Rodolfo

Do you really need to ‘unit’ test this code? Why not integration test with the embedded eventstore? I believe the internal constructors are a deliberate design choice.

Thanks João.

Unit vs Integration is not really my concern; I’m pragmatic about it. Although if by “unit” we mean being faster, simpler, with less dependencies and more deterministic (no threads, external components, etc) then I see it as an advantage and I would be tempted to revert your question and say “why can it not be unit tested?” :slight_smile:

What I would like from the GetEventStore API is a way to test the “sad” path (opposite of the happy path?), where error/alternative conditions are handled. For example, in the snippet below:

var eventReadResult = EventStoreConnection.ReadEventAsync(“some_stream_snapshots”, -1, true).Result;
if (eventReadResult.Status == EventReadStatus.Success && eventReadResult.Event != null)
{
// Happy path
}
else if (eventReadResult.Event == null) { /* I’m pretty sure this shouldn’t happen but you should code deffensively. Log, crash, etc. /}
else if (eventReadResult.Status == EventReadStatus.NotFound) { /
There was no snapshots stream. Probably projections haven’t been enabled in the server. Log, crash. */ }
else if (…) { … other conditions }
how would I test everything other than the first if ()?

As far as I have seen the embedded engine is not a mock but a real implementation and I haven’t seen a way to force it to return NoStream or StreamDeleted.

Thanks and any help is greatly appreciated.

Rodolfo

I’d really like to have this also.

The private constructors are making things like testing that I deserialize from the event store hard.

While I could write as an integration test, I’d prefer to write unit tests. They are quicker/cheaper to run. I’ve wrapped part of the API in my own GESWrapper, but I’m quickly discovering I have to implemented clones of all the datastructures I want. Eg StreamEventsSlice->ResolvedEvent[]->RecordedEvent etc.

It’s getting pretty unwieldy pretty quickly. What is the benefit in locking the user out from creating these datastructures?.

I have also just started with EventStore and have been writing a messaging gateway plugin for ServiceStack that uses the .NET client. I have struggled with unit tests due to the lack of public constructors which means I have not been able to mock out ResolvedEvent, etc.

There is a reason why its like this namely its don't mock data. The
decision to leave them private was done to make it hard for people to
do things they likely shouldn't be doing.

"As far as I have seen the embedded engine is not a mock but a real
implementation and I haven't seen a way to force it to return NoStream
or StreamDeleted."

Read a stream that doesn't exist.
Read a stream that has been deleted.

Your surface area interacting with ES should be very small and domain
specific you should not be creating your own concept of ResolvedEvent
etc. Instead you should be wrapping the functionality that is needed
(EG you don't interact through ResolvedEvent you interact through say
your own event types). Part of the reason why these are private is to
prevent people from passing them around everywhere and creating a
large dependency (if you create your own concept of resolvedevent and
translate between this is likely the wrong level of abstraction). As
an example:

IMessagePublisher {
     publish<T>(T message) where T:Message {}
}

IMessageSubscriber {
     Observable<Message> subscribe(string topic)
}

Everywhere else in your code you test with mocks of these interfaces.
For the implementations of these interfaces that talk to event store
you would test them as an integration test with a embedded/real node.

Part of this can be seen in the questions (how do I force it to return
NoStream/Stream deleted). These tests then show *when* these
situations happen and also work as specifications of the behaviour you
are expecting from the store. If we upgrade and break that behaviour
you get a broken test! There are however a few that are hard to make
happen...

It is of course trivial to make these constructors public and since so
many people are wanting it we will discuss it, but I want people to
see it is a deliberate design decision and that often where you want
to use them is actually leading towards not-so-great tests. In my mind
for every one place someone will use it appropriately if we make them
public there will be 10 who use them inappropriately.

Cheers,

Greg

http://www.davesquared.net/2011/04/dont-mock-types-you-dont-own.html