How can I raise an event on a mocked BackgroundWorker? - unit-testing

I am trying to test how my class reacts on to what happens when the BackgroundWorker fires the RunWorkerCompleted event.
I am using RhinoMocks (if there is another approach I am willing to try it as well) and the code is as follows:
//arrange
var bw1 = MockRepository.GenerateStub<BackgroundWorker>();
Action work1 = () => Thread.Sleep(1);
WorkQueueProcess processInQueue = new WorkQueueProcess(bw1) { Work = work1 };
var tested = new WorkQueue() { processInQueue };
// act
bw1.Raise(
bw => bw.RunWorkerCompleted +=
null,
bw1,
new RunWorkerCompletedEventArgs(null, null, false)
);
// assert
Assert.AreEqual(false, tested.IsBusy);
I am getting an exception that says:
Invalid call, the last call has been
used or no call has been made (make
sure that you are calling a virtual
(C#) / Overridable (VB) method).
What am I doing wrong ? Is it because BackgroundWorker has no virtual methods? I thought I should be able to raise an event regardless, because event are hardly ever virtual.

Only the class that defines an event can raise that event. That is simply how the event system in .NET works.
The Raise method provided by RhinoMocks is intended to be used with interfaces that define events. In that case, any class implementing that interface owns its own event, and thus is able to raise it. That is also true for the run-time emitted types generated by RhinoMocks.
However, when it comes to classes, even sub-types can't raise events defined by their supertypes, which is why we have the OnEvent coding idiom.
BackgroundWorker does have the OnRunWorkerCompleted method that will raise the event. This method is virtual, so if you can get RhinoMocks to invoke this protected method, you should be able to raise the event.
I'm using Moq, which can't do that - I can't remember if RhinoMocks has the ability to invoke protected members.
Otherwise, you can derive a test-specific class from BackgroundWorker and add a public method that invokes OnRunWorkerCompleted.
As a closing remark, however, I would strongly recommend that you don't try to unit test multithreaded code - along that road lies only pain...

Related

Mocking/stubbing whether or debug log is enabled?

How do I write a mock test that allows me to validate that an inaccessible property (debugLog) is set to true? Do I try to find a way to find the value of the property? Do I verify that console.debug is set? Does a spy make sense in this situation or should I use a stub?
Class X
let showDebugLogs = false,
debugLog = _.noop
/**
* Configures Class X instances to output or not output debug logs.
* #param {Boolean} state The state.
*/
exports.showDebugLogs = function (state) {
showDebugLogs = state;
debugLog = showDebugLogs ? console.debug || console.log : _.noop;
};
Unit Test
describe('showDebugLogs(state)', function () {
let spy;
it('should configure RealtimeEvents instances to output or not output debug logs', function () {
spy = sinon.spy(X, 'debugLog');
X.showDebugLogs(true);
assert.strictEqual(spy.calledOnce, true, 'Debug logging was not enabled as expected.');
spy.restore();
});
});
Mock testing is used for "isoloting" a class under test from its environment to decrease its side effects and to increase its test-ability. For example, if you are testing a class which makes AJAX calls to a web server, you'd probably do not want to:
1) wait for AJAX calls to complete (waste of time)
2) observe your tests fall apart because of possible networking problems
3) cause data modifications on the server side
and so on.
So what you do is to "MOCK" the part of your code, which makes the AJAX call, and depending on your test you either:
1) return success and response accompanying a successful request
2) return an error and report the nature of the point of failure to see how your code is handing it.
For your case, what you need is just a simple unit test case. You can use introspection techniques to assert internal states of your object, if this is what you really want to. However, this comes with a warning: it is discouraged. Please see Notes at the bottom
Unit testing should be done to test behavior or public state of an object. So, you should really NOT care about internals of a class.
Therefore, I suggest you to re-consider what you are trying to test and find a better way of testing it.
Suggestion: Instead of checking a flag in your class, you can mock up logger for your test. And write at least two test cases as follows:
1) When showDebugLogs = true, make sure log statement of your mock logger is fired
2) When showDebuLogs = false, log statement of your mock logger is not called.
Notes: There has been a long debate between two schools of people: a group advocating that private members/methods are implementation details and should NOT be tested directly, and another group which opposes this idea:
Excerpt from a wikipedia article:
There is some debate among practitioners of TDD, documented in their
blogs and other writings, as to whether it is wise to test private
methods and data anyway. Some argue that private members are a mere
implementation detail that may change, and should be allowed to do so
without breaking numbers of tests. Thus it should be sufficient to
test any class through its public interface or through its subclass
interface, which some languages call the "protected" interface.[29]
Others say that crucial aspects of functionality may be implemented in
private methods and testing them directly offers advantage of smaller
and more direct unit tests

Laravel Tests pass to model to View

I'm mocking my repository correctly, but in cases like show() it either returns null so the view ends up crashing the test because of calling property on null object.
I'm guessing I'm supposed to mock the eloquent model returned but I find 2 issues:
What's the point of implementing repository pattern if I'm gonna end up mocking eloquent model anyway
How do you mock them correctly? The code below gives me an error.
$this->mockRepository->shouldReceive('find')
->once()
->with(1)
->andReturn(Mockery::mock('MyNamespace\MyModel)
// The view may call $book->title, so I'm guessing I have to mock
// that call and it's returned value, but this doesn't work as it says
// 'Undefined property: Mockery\CompositeExpectation::$title'
->shouldReceive('getAttribute')
->andReturn('')
);
Edit:
I'm trying to test the controller's actions as in:
$this->call('GET', 'books/1'); // will call Controller#show(1)
The thing is, at the end of the controller, it returns a view:
$book = Repo::find(1);
return view('books.show', compact('book'));
So, the the test case also runs view method and if no $book is mocked, it is null and crashes
So you're trying to unit test your controller to make sure that the right methods are called with the expected arguments. The controller-method fetches a model from the repo and passes it to the view. So we have to make sure that
the find()-method is called on the repo
the repo returns a model
the returned model is passed to the view
But first things first:
What's the point of implementing repository pattern if I'm gonna end up mocking eloquent model anyway?
It has many purposes besides (testable) consisten data access rules through different sources, (testable) centralized cache strategies, etc. In this case, you're not testing the repository and you actually don't even care what's returned, you're just interested that certain methods are called. So in combination with the concept of dependency injection you now have a powerful tool: You can just switch the actual instance of the repo with the mock.
So let's say your controller looks like this:
class BookController extends Controller {
protected $repo;
public function __construct(MyNamespace\BookRepository $repo)
{
$this->repo = $repo;
}
public function show()
{
$book = $this->repo->find(1);
return View::make('books.show', compact('book'));
}
}
So now, within your test you just mock the repo and bind it to the container:
public function testShowBook()
{
// no need to mock this, just make sure you pass something
// to the view that is (or acts like) a book
$book = new MyNamespace\Book;
$bookRepoMock = Mockery::mock('MyNamespace\BookRepository');
// make sure the repo is queried with 1
// and you want it to return the book instanciated above
$bookRepoMock->shouldReceive('find')
->once()
->with(1)
->andReturn($book);
// bind your mock to the container, so whenever an instance of
// MyNamespace\BookRepository is needed (like in your controller),
// the mock will be loaded.
$this->app->instance('MyNamespace\BookRepository', $bookRepoMock);
// now trigger the controller method
$response = $this->call('GET', 'books/1');
$this->assertEquals(200, $response->getStatusCode());
// check if the controller passed what was returned from the repo
// to the view
$this->assertViewHas('book', $book);
}
//EDIT in response to the comment:
Now, in the first line of your testShowBook() you instantiate a new Book, which I am assuming is a subclass of Eloquent\Model. Wouldn't that invalidate the whole deal of inversion of control[...]? since if you change ORM, you'd still have to change Book so that it wouldn't be class of Model
Well... yes and no. Yes, I've instantiated the model-class in the test directly, but model in this context doesn't necessarily mean instance of Eloquent\Model but more like the model in model-view-controller. Eloquent is only the ORM and has a class named Model that you inherit from, but the model-class as itself is just an entity of the business logic. It could extend Eloquent, it could extend Doctrine, or it could extend nothing at all.
In the end it's just a class that holds the data that you pull e.g. from a database, from an architecture point of view it is not aware of any ORM, it just contains data. A Book might have an author attribute, maybe even a getAuthor() method, but it doesn't really make sense for a book to have a save() or find() method. But it does if you're using Eloquent. And it's ok, because it's convenient, and in small project there's nothing wrong with accessing it directly. But it's the repository's (or the controller's) job to deal with a specific ORM, not the model's. The actual model is sort of the outcome of an ORM-interaction.
So yes, it might be a little confusing that the model seems so tightly bound to the ORM in Laravel, but, again, it's very convenient and perfectly fine for most projects. In fact, you won't even notice it unless you're using it directly in your application code (e.g. Book::where(...)->get();) and then decide to switch from Eloquent to something like Doctrine - this would obviously break your application. But if this is all encapsulated behind a repository, the rest of your application won't even notice when you switch between databases or even ORMs.
So, you're working with repositories, so only the eloquent-implementation of the repository should actually be aware that Book also extends Eloquent\Model and that it can call a save() method on it. The point is that it doesn't (=shouldn't) matter if Book extends Model or not, it should still be instantiable anywhere in your application, because within your business logic it's just a Book, i.e. a Plain Old PHP Object with some attributes and methods describing a book and not the strategies how to find or persist the object. That's what repositories are for.
But yes, the absolute clean way is to have a BookInterface and then bind it to a specific implementation. So it could all look like this:
Interfaces:
interface BookInterface
{
/**
* Get the ISBN.
*
* #return string
*/
public function getISBN();
}
interface BookRepositoryInterface()
{
/**
* Find a book by the given Id.
*
* #return null|BookInterface
*/
public function find($id);
}
Concrete implementations:
class Book extends Model implements BookInterface
{
public function getISBN()
{
return $this->isbn;
}
}
class EloquentBookRepository implements BookRepositoryInterface
{
protected $book;
public function __construct(Model $book)
{
$this->book = $book;
}
public function find($id)
{
return $this->book->find($id);
}
}
And then bind the interfaces to the desired implementations:
App::bind('BookInterface', function()
{
return new Book;
});
App::bind('BookRepositoryInterface', function()
{
return new EloquentBookRepository(new Book);
});
It doesn't matter if Book extends Model or anything else, as long as it implements the BookInterface, it is a Book. That's why I bravely instantiated a new Book in the test. Because it doesn't matter if you change the ORM, it only matters if you have several implementations of the BookInterface, but that's not very likely (sensible?), I guess. But just to play it safe, now that it's bound to the IoC-Container, you can instantiate it like this in the test:
$book = $this->app->make('BookInterface');
which will return an instance of whatever implementation of Book you're currently using.
So, for better testability
Code to interfaces rather than concrete classes
Use Laravel's IoC-Container to bind interfaces to concrete implementations (including mocks)
Use dependency injection
I hope that makes sense.

Can loopback.io operation hooks be registered only once per model?

I'm trying out operation hooks http://docs.strongloop.com/display/public/LB/Operation+hooks
Here is what I did in app code:
mymodel.observe('before save', doSomething);
//after some time elapses or based on an event we want to change the behaviour
mymodel.observe('before save', doSomethingElse);
var doSomething = function (ctx, next) {
//do something
next();
};
var doSomethingElse = function (ctx, next) {
//do something else
next();
};
When I test this code I find that always doSomething is executed which makes me wonder if the observer function can be registered only once per model or is it a bug?
If it is as per design, could you please tell the reason behind it?
Disclaimer: I am a core developer of LoopBack and the author of Operation hooks.
after some time elapses or based on an event we want to change the behaviour
The Operation hooks do not support unregistering of handler functions yet. Each call of observe() adds the handler to the list of methods invoked when a hook is triggered.
When I test this code I find that always doSomething is executed which makes me wonder if the observer function can be registered only once per model or is it a bug?
You can register multiple observers. Once you have registered doSomething, it will be always called. When you register doSomethingElse, it will be called too, after doSomething returns via next().
You can now unregister all observers with the clearObservers method and remove a single observer with the removeObserver method. See the ObserverMixin documentation.
According to the changelog, this feature was added in version 2.23.0 of the datasource juggler.

Dll's, Message Boxes, and Unit Testing

Ok... I am working on a dll that manages some configured settings (I won't bore you with the details and reasoning here as that doesn't apply). I have a class for referencing assemblies to use to interface with this system. this class has a Load() method. When there are read or validation errors, I currently have it showing a message box. I didn't feel it should be the responsibility of the referencing assembly to manage this? Or am I wrong? Currently this is creating havoc with creating unit tests, so I'm considering adding a property to suppress messages, but still allow the exceptions to be thrown. I read on one other SO posting where someone was recommended to use IoC and a dialog result helper class. The illustration was with Constructor Injection... but that would again put that responsibility into the hands of the referencing assembly. What's best practice in this case?
Personally, I think you're wrong - sorry. The DLL's responsibility is to notify of the errors, the calling code's responsibility is to determine what to do with that notification. If it's a GUI, then it can show a dialog box. If it's a unit test, it can test appropriately. If it's a website, it can write the notification out in HTML to the user. If it's a service of some sort, it can log it. And so on.
You can use a delegate to send messages to be handled elsewhere. I have made an example below using a unittest:
public delegate void ErrorHandlingDelegate(Exception exception); //The delegate
public class AsseblymRefClass //Your class doing the business logic
{
public void DoStuff(ErrorHandlingDelegate errorHandling) //Passing the delegate as argument
{
try
{
//Do your stuff
throw new Exception();
}
catch (Exception ex)
{
errorHandling(ex); //Calling the delegate
}
}
}
//Another class that can handle the error through its method 'HandleErrorsFromOtherClass()'
public class ErrorHandlingClass
{
public void HandleErrorsFromOtherClass(Exception exception)
{
MessageBox.Show(exception.Message);
}
}
[Test]
public void testmethod() //The test that creates your class, and a class for the errorhandling, and connects the two
{
ErrorHandlingClass errorHandling = new ErrorHandlingClass();
AsseblymRefClass assemblyRef = new AsseblymRefClass();
assemblyRef.DoStuff(errorHandling.HandleErrorsFromOtherClass);
}
Any method that fits the delegate can be used. Thus, you can replace your production code, with something that doesn't show a messagebox when unit testing.

How do you assert a generic method was called with Rhino Mocks?

I have the following test to verify that my repository is calling it's respective session (I've rewritten it to highlight the actual problem):
[Test]
public void Why_Does_This_Fail()
{
var objectUnderTest = new SomeGenericsProblem();
var fakeSession = MockRepository.GenerateMock<ISession>();
fakeSession.Expect(s => s.Query<SomeClass>());
objectUnderTest.NotWorking<SomeClass>();
fakeSession.AssertWasCalled(t => t.Query<SomeClass>());
}
but when I run the test I get this:
System.InvalidOperationException :
Invalid call, the last call has been
used or no call has been made (make
sure that you are calling a virtual
(C#) / Overridable (VB) method).(C#) / Overridable (VB) method).
Any ideas what I'm doing wrong here? The session that I'm mocking is an interface, so it has to be virtual/overridable.
I have a feeling it has something to do with the fact that my Query method is a generic, but I don't know any other way to express what I'm trying to test.
Also, If I remove the part that sets up the expectation (i.e. this line of code:)
fakeSession.Expect(s => s.Query<SomeClass>());
I get a different exception which is equally confusing to me:
System.InvalidOperationException : No
expectations were setup to be
verified, ensure that the method call
in the action is a virtual (C#) /
overridable (VB.Net) method calloverridable (VB.Net) method call
So I figured out what was wrong.
ISession comes from NHibernate, which I probably should have mentioned.
The reason why this is cruicialy important is because
session.Query<T>
(which is what I'm trying to mock), is an EXTENSION METHOD.
Rhino Mocks apparently does not have the capability of mocking extension methods, hence why it's giving me the weird error.
So hopefully I'll have saves someone else the time and agony I've gone through in trying to figure out why my test won't pass.
The only solution that I've read about for this is to actually change the design of the extension method (which I can't do because it's part of NHibernate), or to use a different mocking framework like TypeMock.
[Test]
public void Query_WhenCalled_CallsSessionQuery()
{
// arrange
var session = MockRepository.GenerateStub<ISession>();
var r = new Repository(session);
// act
r.Query<SomeClass>();
// assert
session.AssertWasCalled(s => s.Query<SomeClass>());
}