Run function/behaviour after all behaviours ended in Pony - unit-testing

I have a simple Publish-Subscriber that I want to write tests for.
The methods called here are all behaviours, except get_number_consumed_messages that would be a function.
class iso _SinglePubSub is UnitTest
fun name(): String => "single publish/consume"
fun apply(h: TestHelper) =>
let p = Publisher("publisher message", h.env.out)
let queue = Queue(1, h.env.out)
let c = Consumer(h.env.out)
p.publish_message(queue)
p.publish_message(queue)
c.consume_message(queue)
c.consume_message(queue)
//Run after all behaviours are done
let n = c.get_number_consumed_messages()
h.assert_eq[USize](2, n)
How would someone implement the get_number_consumed_messages function/behaviour or how would you have to modify the test function?

First of all, c.get_number_consumed_messages() must be a behaviour as well. It is the only way to let one actor communicate with another. This has the added benefit of behaviours being run in the same order as they are called, which means c.get_number_consumed_messages() would run after both calls to c.consume_message(queue).
Given that, since Consumer is also an actor, calling it with behaviours -- and not methods -- means that we cannot return data from it directly. To actually receive data from another actor, you should use the Promise pattern, for example:
use "promises"
actor Consumer
var message_count: USize = 0
be consume_message(queue: OutStream) =>
... // Do some things
message_count = message_count + 1
... // Do other things
be get_number_consumed_messages(p: Promise[USize]) =>
p(message_count)
To actually test it, you would need to follow an adapted version of the Testing Notifier Interactions pattern for long tests, for example:
use "ponytest"
use "promises"
class iso _SinglePubSub is UnitTest
fun apply(h: TestHelper) =>
h.long_test(2_000_000_000)
... // Produce and consume messages
let p = Promise[USize]
p.next[None]({(n: USize): None =>
h.assert_eq[USize](2, n)
h.complete(true) })
c.get_number_consumed_messages(p)
(Notice the extra calls to h.long_test and h.complete, as well as the promise wrapping a lambda with the end of our test.)
For more information on these concepts, I would recommend familiarizing yourself with the stdlib documentation on Promises and the "Long tests" section of Ponytest.

Related

Mixing StateT and MonadUnliftIO

I'm not sure on the best name for my question, but I seem to have coded myself into a corner somewhat. Or at least I am faced with a slightly awkward design descision within my hspec test suite for my project.
My project has to make some third party API calls, and in HSpec I am trying to make it so these can be faked using a transformer implemented using StateT, that can be placed inside a test stack to enable the ability to 'fake' these API calls. I always want to stub these calls out in unit tests, I never want to hit the real API, ever.
The way I am 'stubbing' calls is by defining all of my systems effects with typeclasses and providing a different instance when in test. So for example I would have a class like:
class FireApiGetRequest m where
fireApiGetRequest :: GetRequest -> m (Either ApiError GetReponse)
instance FireApiGetRequest Hander where
fireApiGetRequest = -- real world implementation
I have two transformer stacks for my tests currently one is known as AppTestIO, and AppTestPureM.
AppTestIO is made up of a ReaderT that contains a connection pool to a real test database and some test configuration settings, and AppTestPureM is a type alias for StateT FakeDatabaseCalls Gen, much in the same way as I write out the API calls with typeclasses, database calls are also factored out into type classes and 'stubbed' out in the same way. This works well, only I would like to add a transformer layer to both stacks, that mocks the third party API. In my mind I should be able to define a transformer that can sit within both of these transformer stacks and give me the ability to fake these API calls:
type AppTestPureM = StateT FakedDatabaseCalls (ThirdPartyApiMocksT Gen)
type AppTestIO = ThirdPartyApiMocksT (AppTestT IO)
newtype AppTestT m a = AppTestT
{ unAppTestT :: ReaderT TestEnv m a
}
On the face of it this seems like a great idea because it means I can stub out these API calls regardless of whether or not the test is hitting the real database, basically.
For the instances, I have no issue defining instances for the API calls in test:
instance FireApiGetRequest ThirdPartyApiMocksT where
fireApiGetRequest = -- test implementation, access state and return value based on that
instance FireApiGetRequest m => FireApiGetRequest (StateT s m) where
fireApiGetRequest = lift . fireApiGetRequest
And I can define helper functions in my test to get the instances to return the fake data that I want:
stubApiGetRequest :: Monad m => (Either ApiError GetResponse) -> ThirdPartyApiMocksT m ()
stubApiGetRequest returnVal = undefined -- store `returnVal` in the state for use in typeclass instance
My issue arises when I actually start using these instances within my tests. For those functions in my app that hit the database (that aren't yet stubbed out with typeclass instances), they ultimately are using runSqlPool, which uses MonadUnliftIO, and MonadUnliftIO is effectively forbidding me from mixing these together.
The approach to achieve 'state' while using MonadUnliftIO is to use ReaderT + MVar instead. I don't have a huge issue with this normally, my only problem here is that my PureM stack is based around StateT, and also does not run in IO, because it is used to run 'effectful' computations using fake data in order to write the test in a pure way, with no IO. This also means I can use quickcheck to test these functions if that is something I want to do. I am aware there is quickcheck-monadic so having these functions result in IO may not be the end of the world, but I would like retain AppTestPureM a -> Gen a. Using ReaderT + MVar here in this situation would make it so that these tests then depend on IO. So these two test stacks are contradictory.
I suppose that illustrates the situation I am in now. I am not sure how exactly to proceed from here.

Sinon stub instance method declared in mapDispatchToProps

New to testing and React Redux, so I may be conflating a few issues here. I will only present one example, but I have tried many different combinations of mount(), shallow(), instance(), stub, spy and more.
Given a component, where setFooData() updates redux state and Foo.props.data:
const mapDispatchToProps = (dispatch, props) => ({
setFooData(fooId, data) {
dispatch(Actions.setFooData(fooId, data));
},
});
...
return (
<div fooId={this.props.fooId}>
<Foo {...fooProps}/>
</div>
);
I would like to write some tests around the conditions under which setFooData() is called, namely conditions in lifecycle methods like componentDidMount() and componentWillReceiveProps().
Because setFooData() involves server calls and more, and because these tests merely concern the view layer and how the component renders as a result of Foo.props.data being set eventually by setFooData(), setFooData() seems like a good candidate for stub.
Therefore, Enzyme's shallow(), rather than mount(), seems appropriate, correct? In any case, when I try to stub setFooData():
let wrapper = return shallow(<Foo {...props}/>);
let stub = sinon.stub(wrapper.instance(), 'setFooData');
I receive the error:
Attempted to wrap undefined property setFooData as function
Upon inspection, wrapper.instance() yields an object where setFooData() is indeed not defined, but according to other examples, I would think it should be.
Furthermore, setFooData() does exist on wrapper.instance().selector.props, and while let stub = sinon.stub(wrapper.instance().selector.props, 'setFooData'); avoids the error, when I inspect the object setFooData() =/= stub, and the function is not called as per the test.
When I use mount() instead,
let wrapper = mount(<Provider store={store}><Foo {...props}/></Provider>);
let componentDidMountSpy = sinon.spy(Foo.prototype, 'componentDidMount');
let componentWillReceivePropsSpy = sinon.spy(Foo.prototype, 'componentWillReceiveProps');
expect(componentDidMountSpy.called).to.be.true; //passes
expect(componentWillReceivePropsSpy.called).to.be.true; //passes
expect(stub.called).to.be.true; //fails
I receive a different error that appears related to the body of setFooData(), so setFooData() is called but the function is not actually stubbed to prevent its real body from being executed.
Thanks for any help to clarify my understanding.
I think you're taking the hardest path. You should test your component in isolation, not the connected one. If you test the connected component you're making an integration test and double testing that connect indeed works. That's already tested in react-redux for you.
Instead, test your action creators by themselves in unit tests.
Then, export your component as named export without connecting and use the default export for the connect version.
That way you can simply import the pure-React version and pass anything you want as props, in order to make easy assertions afterwards.
If you need to specifically test that something happens in those lifecycle methods, you can call those methods from the instance:
const fakeActionCreator = sinon.spy()
const subject = mount(<MyComponent doSomething={ fakeActionCreator } />)
subject.instance().componentDidMount()
assert.equal(fakeActionCreator.callCount, 1)

How to verify if a stream has been copied on a fileSystem

I want to write a unit test that check a stream has been copied on the disk :
The problem is CopyTo method is not virtual so I can't use
inputMemoryStreamMock.Verify(c => c.CopyTo(outputMemoryStreamMock.Object));
and I don't know how to mock a stream :-/
here is my test method :
[TestMethod]
public void Save_Stream_On_DestinationPath()
{
// Arrange
string fileName = "filename.pdf";
DateTime date = new DateTime(2013, 9, 27);
var serverConfigMock = new Mock<IServerConfigurationManager>();
serverConfigMock.Setup(config => config.ReportingBasePath).Returns(#"c:\reportsFolder");
var factoryReportFileResultMock = new Mock<IReportFileResultFactory>();
var timeManagementMock = new Mock<ITimeManagement>();
timeManagementMock.Setup(c => c.GetServerDate()).Returns(date);
var fileSystemMock = new Mock<IFileSystem>();
var fileInfoFactory = new Mock<IFileInfoFactory>();
var directoryInfoBaseMock = new Mock<DirectoryInfoBase>();
var inputMemoryStreamMock = new Mock<Stream>();
var outputMemoryStreamMock = new Mock<Stream>();
var reportFileHelper = new ReportFileHelper(serverConfigMock.Object, factoryReportFileResultMock.Object, fileSystemMock.Object);
inputMemoryStreamMock.Setup(c => c.CanRead).Returns(true);
outputMemoryStreamMock.Setup(c => c.CanWrite).Returns(true);
outputMemoryStreamMock.Setup(c => c.CanWrite).Returns(true);
fileSystemMock.Setup(c => c.FileInfo).Returns(fileInfoFactory.Object);
fileSystemMock.Setup(c => c.File.Create(It.IsAny<string>())).Returns(outputMemoryStreamMock.Object);
fileSystemMock.Setup(c => c.Directory.CreateDirectory(It.IsAny<string>())).Returns(directoryInfoBaseMock.Object);
// Act
reportFileHelper.Save(inputMemoryStreamMock.Object, fileName, timeManagementMock.Object);
// Assert
inputMemoryStreamMock.Verify(c => c.CopyTo(outputMemoryStreamMock.Object));
}
And here is the method to test :
public void Save(Stream portfolioReportFileInfoBase, string destinationName, ITimeManagement timeManagement)
{
string destinationPath = GetDestinationPath(timeManagement);
string destinationFileUri = Path.Combine(destinationPath, destinationName);
FileSystem.Directory.CreateDirectory(destinationPath);
using (var fileStream = FileSystem.File.Create(destinationFileUri))
{
portfolioReportFileInfoBase.CopyTo(fileStream);
}
}
Thank you
My take on a couple of things :
Readability
I'm not sure your test reads very nicely. Why do you declare a fileName variable as though it were important while you don't even assert on it ? Same goes for date. This clutters your test with unneeded detail. Inline values or Anonymous Variables allow for a better signal/noise ratio.
Then why do you set up CreateDirectory() to return something ? You never use that return value, do you ? I suggest you get rid of that and the directoryInfoBaseMock variable. Same with FileInfo and fileInfoFactory. Your test needs to contain the bare minimum to set up the objects you want to verify, and nothing more. If you need to build a deep, complex graph of objects just to test one simple thing, there's generally a problem somewhere.
Design
The second thing that raises an alarm is that Save() mixes multiple language levels. When you read it, it seems to be at the same time about :
Portfolios and reports
Time management
A lot of lower level filesystem stuff
This is often a sign that an object tries to handle too much, violating the Single Responsibility Principle.
What I would do is distribute these responsibilities across separate objects.
Why does Save() need to know about time management ? Sure, we use time management to compute the destination path, but wouldn't it be better aligned with the language level and responsibility level of a Save() method if we directly passed it the destination path instead ?
Why does Save() need to know about portfolios and reports ? Well, there's basically no reason. You could just rename portfolioReportFileInfoBase to... stream.
Save() and GetPath() could then be moved to a separate lower-level filesystem wrapper class (IFileSystem is a perfect candidate), removing the tight coupling between ReportFileHelper and the filesystem.
Don't try to test that your report is written to the disk using mocks. Do it with an integration test. Don't mock types you don't own. Use mocks only to test how your own classes talk to each other. Wrap external libraries/platforms into wrapper objects, and write integration tests at the boundaries of your application to verify that your wrappers play well with those external libraries/platforms.
You'll have to use an isolation framework like TypeMock Isolator or Microsoft Fakes to test this case if you're not willing to change the code of the Save method, since CopyTo can't be mocked by Moq.
You already encapsulated access to the filesystem behind IFileSystem; why not just add a method like CopyStreamToPath?
public void Save(Stream portfolioReportFileInfoBase, string destinationName, ITimeManagement timeManagement)
{
string destinationPath = GetDestinationPath(timeManagement);
string destinationFileUri = Path.Combine(destinationPath, destinationName);
FileSystem.Directory.CreateDirectory(destinationPath);
FileSystem.CopyStreamToPath(portfolioReportFileInfoBase, destinationFileUri);
}
and the test:
fileSystemMock.Verify(c => c.CopyStreamToPath(inputMemoryStreamMock.object, It.IsAny<string>()));

Writing unit test to check that event was triggered

I am wondering what is the correct approach. First here is the test code.
describe 'Something', ->
it 'should trigger event', (done) ->
spy = sinon.spy()
instance = new Something()
instance.on("itsdone", spy)
instance.methodCall()
spy.should.have.been.calledOnce
done()
Looks pretty straightforward, but since events are usually asynchronous, this cannot work.
class Something
constructor: ->
#events = {}
on: (event, cb) ->
#events[event] = new signals.Signal() unless #events[event]?
#events[event].add cb
methodCall: ->
# Fire up `itsdone` event when everything else is done
setTimeout (=> #events['itsdone']?.dispatch()), 0
This way test will fail obviously. Then I thought about something like this...
describe 'Something', ->
it 'should be triggering even', (done) ->
instance = new Something()
instance.on("itsdone", done)
instance.methodCall()
This works correctly and when event is not triggered, test will fail after 2 seconds. However there is no verification, that it was triggered only once. Maybe I need another test for that ? Since I already know it's triggered at least once, I can use test with spy after this one probably. Although it seems too much hassle for one event.
Another "dirty" approach could be this:
describe 'Something', ->
it 'should be triggering even', (done) ->
spy = sinon.spy()
instance = new Something()
instance.on("itsdone", spy)
instance.methodCall()
setTimeout ->
spy.should.have.been.calledOnce
done()
, 0
It isn't probably really bulletproof. It would need bigger timeout probably to be sure. However that means tests will take longer to process, which is not good idea.
Do you have any other ideas how this should be solved ?
I think your third choice is the right one:
describe 'Something', ->
it 'should be triggering even', (done) ->
instance = new Something()
instance.on("itsdone", done)
instance.methodCall()
If I understand correctly, your concern is that this doesn't test that the callback is not called twice.
In general it is difficult to test that things don't happen. For example, how long are you going to wait to see if it isn't called a second time? 2 seconds? 2 hours? You really need to use your understanding of the code being tested to know what tests are needed. Unit testing shouldn't be complete black-box testing.
I wouldn't test that it isn't called twice unless I know that the underlying code might break in a way that would cause it to be called twice.

Verifying function call order in a unit test

I want a unit test that verifies 2 function calls happen in the correct order. In the example, the first function encrypts a file and saves it to the file system, and the second function sends the encrypted file to a 3rd party processor (via FTP).
I am using NSubstitute as the mock framework and FluentAssertions to aid in test verification. It does not seem like this is something you can achieve with NSubstitute out of the box.
public void SendUploadToProcessor(Stream stream, string filename)
{
var encryptedFilename = FilenameBuilder.BuildEncryptedFilename(filename);
FileEncrypter.Encrypt(stream, filename, encryptedFilename);
FileTransferProxy.SendUpload(encryptedFilename);
}
[TestMethod, TestCategory("BVT")]
public void TheEncryptedFileIsSent()
{
var stream = new MemoryStream();
var filename = Fixture.Create<string>();
var encryptedFilename = Fixture.Create<string>();
FilenameBuilder
.BuildEncryptedFilename(Arg.Any<string>())
.Returns(encryptedFilename);
Sut.SendUploadToProcessor(stream, filename);
// Something here to verify FileEncrypter.Encrypt() gets called first
FileTransferProxy
.Received()
.SendUpload(encryptedFilename);
}
Try Received.InOrder in the NSubstitute.Experimental namespace.
Something like this (I haven't tested this):
Received.InOrder(() => {
FileEncrypter.Encrypt(stream, filename, encryptedFilename);
FileTransferProxy.SendUpload(encryptedFilename);
});
If you're not comfortable relying on experimental functionality, you will need to set up callbacks to store calls in order, then assert on that.
var calls = new List<string>(); //or an enum for different calls
FileEncrypter.When(x => x.Encrypt(stream, filename, encryptedFilename))
.Do(x => calls.Add("encrypt"));
FileTransferProxy.When(x => x.SendUpload(encryptedFilename))
.Do(x => calls.Add("upload"));
// Act
// Assert calls contains "encrypt","upload" in the correct order
If you do end up trying Received.InOrder, please leave some feedback on the discussion group. If we get some feedback about it working well for others then we can promote it to the core namespace.
Although it is not an answer persee, but verifying the explicit order as part of a unit test is bad practice. You should never test the implementation details. Just make sure the input is properly converted to the output and add some alternative scenarios that basically proof the expected behavior. That's the precise reason why this functionality was deprecated in RhinoMocks and that FakeItEasy doesn't even support it.