How can I test authlogic's current_user in Cucumber? - cucumber

I am trying to use authlogic's test helpers in Cucumber, calling activate_authlogic.
Our application_controller has a current_user_session method.
When we drop into the debugger mid-story, controller returns a Authlogic::TestCase::MockController.
But when we call controller.current_user_session.
The error occurred while evaluating nil.current_user_session.
How does this mock suddenly become a nil?
And does this mock controller know about our application controllers' code?

I don't know authlogic (and if this answer is helpful at all), but where does that mock object come from in the first place? You shouldn't be using any mocks in you cucumber stories. Cucumber is like an integration test, testing the complete Rails Stack.
I use it, to make sure, that my view, controller and model specs haven't diverged from each other.

Related

NUnit Attribute to simulate condition-based Assert.Inconclusive with custom message text

I have some tests that depend on a certain thing being true (access to the internet, as it happens, but that isn't important and I don't want to discuss the details of the condition).
I can very easily write a static helper method which will test the (parameterless) condition and call Assert.Inconclusive("Explanatory Message") if it's true/false. And then call that at the start of each Test which has this requirement.
But I'd like to do this as an Attribute, if possible.
How, in detail, do I achieve that, in NUnit?
What I've tried so far:
There's an IApplyToTest interface, exposed by NUnit, which I can make my Attribute implement, and will allow me to hook into the TestRunner, but I can't get it to do what I want :(
That interface gives me access to an NUnit.Framework.Internal.Test object.
If I call:
test.RunState = RunState.NotRunnable;
then I get something equivalent to Assert.Fail("").
Similarly RunState.Skipped or RunState.Ignored give me the equivalent of Assert.Ignore("").
But none of these are setting a message on the Test, and there's no test.Message = "foo"; or equivalent (that I can see).
There's a test.MakeInvalid("Foo") which does set a message, but that's equivalent to Assert.Fail("Foo").
I found something that looked promising:
var result = test.MakeTestResult();
result.SetResult(ResultState.Inconclusive, "Custom Message text");
But that doesn't seem to do anything; the Test just Passes :( I looked for a test.SetAsCurrentResult(result) method in case I need to "attach" that result object back to the test? But nothing doing.
It feels like this is supposed to be possible, but I can't quite figure out how to make it all play together.
If anyone can even show me how to get to Skipped + Custom Message displayed, then I'd probably take that!
If you really want your test to be Inconclusive, then that's what Assume.That is there for. Use it just as you would use Assert.That and the specified constraint fails, your test result will be inconclusive.
That would be the simplest answer to your question.
However, reading the things you have tried, I don't think you actually want Inconclusive at least not as it is defined by NUnit.
In NUnit, Inconclusive means that the test doesn't count because it couldn't be run. The result basically disappears and the test run is successful.
You seem to be saying that you want to receive some notice that the condition failed. That makes sense in the situation where (for example) the internet was not available so your test run isn't definitive.
NUnit provides Assert.Ignore and Warn.If (also Warn.Unless) for those situations. Or you can set the corresponding result states in your custom attribute.
Regarding implementation... The RunState of a test applies to it's status before anyone has even tried to execute it. So, for example, the RunState may be Ignored if someone has used the IgnoreAttribute or it may be NotRunnable if it requires arguments and none are provided. There is no Inconclusive run sttate because that would mean the test is written to be inconclusive all the time, which makes no ssense. The IApplyToTest interface allows an attribute to change the status of a test at the point of discovery, before it is even run, so you would not want to use that.
After NUnit has attempted to run a test, it gets a ResultState, which might be Inconclusive. You can affect this in the code of the test but not currently through an attribute. What you want here is something that checks the conditions needed to run the test immediately before running it and skips execution if the conditions are not met. That attribute would need to be one that generates a command in the chain of commands that execute a test. It would probably need to implement ICommandWrapper to do that, which is a bit more complicated than IApplyToTest because the attribute code must generate a command instance that will work properly with NUnit itself and with other commands in the chain.
If I had this situation, I believe I would use a Run parameter to indicate whether the internet should be available. Then, the tests could
Assume.That(InternetIsNotNeeded());
silently ignoring those tests or fail as expected when the internet should be available.

Does verifying the mock is need in minitest

I'm reading the mocking capability of minitest.
require "minitest/autorun"
mock = MiniTest::Mock.new
mock.expect(:use_any_string, true, [String])
mock.use_any_string("foo")
## mock.use_any_string(1)
## MockExpectationError: mocked method :use_any_string called with unexpected arguments [1]
## I do not understand the purpose for this
mock.verify
So I do not understand the purpose of using mock.verify since the trying to pass any another type(to use_any_string) other than String result in mock expectation error.
So why should one use assert mock.verify then?
You are right, you cannot set anything else to the configured mock, but if your mock is not called at all, then you can find out with mock.verify. So if your method under test should call the mocked method, you should verify that it was called at all.
You are correct, mock.expect(:use_any_string, true, [String]) will cause the test to fail if the expected call is not made on the mock.
However using mock.verify depends on how you compose your test. In your example you are explicitly calling the method you are testing with mock.use_any_string("foo") so there is no need to also call mock.verify.
You could get into a scenario where you are not making this call explicitly, or are expecting the mock to have had calls made at a certain time. These scenarios would take advantage of mock.verify calls.
(Another note, minitest has recently introduced assert_mock which can be used instead of mock.verify)

How to spy on Apollo Client cache calls for unit testing?

I am using enzyme to "mount" a component wrapped with withApollo, hence it has a client object in context that it finds available in the props. The component writes on the client cache using writeQuery conditionally, and I am writing a unit test that simulates those conditions, I would like to be able to assert that this cache method has been called with the expected arguments.
Following Apollo-Client guidelines, I am using the MockedWrapper. I think this would a good place to intercept the client object and replace its writeQuery function with a mock function. I do not know how or if it is even possible.
Alternatively, I could ditch the MockedProvider and simulate the context entirely, but I do not know the expected object inside the context nor its shape/schema.

cucumber: string to an active record model name

I'm trying to do a DRY cucumber feature and I'm facing a problem of converting a string into an ActiveRecord model name
Given /^the following "(.+)" exist:/ do |mod, table|
table.hashes.each do |t|
mod.create!(t)
end
assert mod.all.count == table.hashes.size
end
that gives
undefined method `create!' for "Balloon":String (NoMethodError)
More elegant solution might be to use a factory, but I'm wondering whether it is possible to use the above approach?
You could look into constantize which turns a String into a constant. Try:
"Balloon".constantize.create!(t)
BUT: Using your app code (models in particular) in a Cucumber step is code smell. Your integration tests shouldn't rely on the code under test at all—think of your app as a black box when you implement Cucumber steps. (Also think of a refactoring of your models that require you to go back and change your Cucumber steps—that's your first clue that you're on the wrong track!)
What you could do to improve this is create the models using an API (if your app implements one).
That way, you only rely on those parts of your app that are public-facing.
On another note: Your Given shouldn't have an assertion, it's more like a before hook in RSpec, setting up a condition for a later assertion...

Grails unit test for domain class insertBefore

How can I test the initBefore method of Groovy Domain-Classes with a unit test in Grails?
I created the dummy object but the beforeInsert-method is not called until myObject.save() is invoked and save is unavailable in the testing environments.
Edit: its a unit-test. there is no error, but the method beforeInsert is not called
beforeInsert is called during unit tests. I can verify this in my tests. A couple things to consider:
ensure you use a beforeInsert method, and not a closure. A closure will not work correctly.
it is called when the object is flushed, so perhaps you are having silent save errors beforehand. In your test when you save the object do .save(flush: true, failOnError: true)
Do you want test if the beforeInsert method is being called or the logic of beforeInsert is correct?
If you want to test if beforeInsert is being called the test class should extend the GrailsUnitTestCase. Do so should give you mocking capabilities and add all the methods like save() and validate(). You can verify if the mocked object called the beforeInsert method or not when you do a save().
If you are testing the logic of beforeInsert then you don't need to mock it. You can create the object and test the logic just like other unit test.
Hope this helps.
Just creat a domain object and save() it. Then check whether or not the "beforeInsert" manipulated your Object.
save() is available in the testing enviroments. Please show your Stacktrace when calling myDomainobject.save()
I had the same exact problem! In GORM (at least until the current version) the save method does not take effect immediately just because it is called! If you want it to take effect right away you need to specify flush:true like this domain.save(flush:true).
it says here http://grails.org/doc/2.2.x/ref/Domain%20Classes/save.html
The save method informs the persistence context that an instance
should be saved or updated. The object will not be persisted
immediately unless the flush argument is used:
To answer your question, beforeInsert is not called until the save is persisted (save takes effect) therefor you should invoke save with flush to test beforeInsert and beforeUpdate methods.
Hope this helps!

Resources