Update this has been filed as a bug in ColdFusion, https://bugbase.adobe.com/index.cfm?event=bug&id=3546237
I've been having a problem with CF9 and NULL POINTER errors that do not appear to be an issue within Railo. I created a simple CFC and associated mxunit unit test to confirm this with.
On Railo (4.0.4) both unit tests pass. On Coldfusion (9.0.1), the unit test getMetaDataBeforeMethodInvocation fails with NULL POINTER error on the GetMetaData call.
At present I can only surmise that CF9 does not have access to the full metadata following ObjectLoad until a method within that component is called. Is anyone able to shed more light on this problem, and/or offer a better solution than to ensure that a method within the object is called prior to doing getMetaData?
Here is the CFC
// NullError.cfc
component {
public NullError function init() {
variables.uuid = CreateUUID();
return this;
}
public string function getUUID() {
return uuid;
}
}
and associated unit test
// NullErrorTest.cfc
component extends='mxunit.framework.TestCase' {
private any function setupTheTests() {
var o = new NullError();
debug(o.getUUID());
// Dump meta data
debug(GetMetaData(o));
// Save and load it, and return
return ObjectLoad(ObjectSave(o));
}
public void function getMetaDataBeforeMethodInvocation() {
var o = setupTheTests();
// Get meta data, and then get uuid, expecting this to ERROR (NULL POINTER)
debug(GetMetaData(o)); // CF FAILS HERE, RAILO DOES NOT
debug(o.getUUID());
}
public void function getMetaDataAfterMethodInvocation() {
var o = setupTheTests();
// Get uuid, and then get meta data, expecting this to be ok
debug(o.getUUID());
debug(GetMetaData(o));
}
}
I can confirm this buggy behaviour in both CF 9.0.2 and 10.0.9.
I'd raise a bug if I was you.
The repro case can be simplified a lot from what you have:
// C.cfc
component {}
<!--- test.cfm --->
<cfscript>
o1 = new C();
writeDump(getMetaData(o1)); // OK
o2 = objectLoad(objectSave(o1));
writeDump(getMetadata(o2)); // breaks
</cfscript>
I don't know what to suggest by way of work-around, given it's so clearly and fundamentally broken.
Related
Before starting, I have used Moq to mock things in unit tests for years. This should be a simple mock verify, but for whatever reason moq is not matching the invocation on the Mock when it occurs. I've manually tested, it is hit. I've debugged the test and compared actual vs. expected values (they match), I've scoured SO and its multitudes of people doing blatantly wrong things and I cannot figure out why this isn't working. Help appreciated.
The unit test is a very simple test of checking if BulkInsert is called at the end of a void returning function. Sample code:
Code:
public interface IDependencyService
{
void BulkInsert(IList<T> items);
}
public class MyServiceClass
{
private readonly IDependencyService _service;
/* ctor and all that jazz */
public void Run()
{
/* do things to the data */
_service.BulkInsert(items); // where items is an IList<T>
}
}
Test:
public class ServiceTests
{
[Fact]
public void ServiceRun_Calls_DependencyBulkInsert()
{
var dependencyMock = new Mock<IDependencyService>();
List<T> expected = /* somehow build expected values */
dependencyMock
.Setup(mock => mock.BulkInsert(It.IsAny<IList<T>>()));
var sut = new MyServiceClass(dependencyMock.Object);
sut.Run();
dependencyMock.Verify(mock => mock.BulkInsert(expected), Times.Once());
}
}
Error message:
Expected invocation on the mock once, but was 0 times: mock => mock.BulkInsert([ThresholdCheck])
Performed invocations:
Mock<IThresholdCheckHandler:1> (mock):
IThresholdCheckHandler.GetQueuedChecks()
IThresholdCheckHandler.BulkInsert([ThresholdCheck])
If I change expected to It.IsAny<T>() in the Verify call, test passes. This leads me to believe that maybe somehow the objects passed from expected are somehow different from the objects generated when running the program. However as stated I've went through with the debugger and manually compared every value in the actual list to the expected list of values in the test and they are exactly the same.
This then leads me to believe that I'm just a stupid bipedal monkey clicking at a keyboard and that the problem is right in front of me and I'm just not seeing it. Any help or set of eyes is appreciated.
As per NKosi's comment, Verify operates via. reference when using reference types. I was confused as I'd used Verify in the past for simple things like ints and strings but was unaware of that quirk. One would assume with Verify that it would check the equivalency of actual vs. expected, but no.
Regardless then, as per Quercus's comment I adjusted my test to this in order to continue with my day:
public class ServiceTests
{
[Fact]
public void ServiceRun_Calls_DependencyBulkInsert()
{
var dependencyMock = new Mock<IDependencyService>();
List<T> actual = new List<T>();
List<T> expected = /* somehow build expected values */
dependencyMock
.Setup(mock => mock.BulkInsert(It.IsAny<IList<T>>()))
.Callback<List<T>>(l => actual = l);
var sut = new MyServiceClass(dependencyMock.Object);
sut.Run();
actual.Should().BeEquivalentTo(expected);
}
}
and this solution works for me. thanks to you both for helping me realize my mistake.
For few test cases I'm trying to follow a DRY principle, where only the interactions are different with same test case conditions. I'm not able to find a way to implement multiple methods in the interaction { } block.
As mentioned in http://spockframework.org/spock/docs/1.3/interaction_based_testing.html#_explicit_interaction_blocks, I'm using interaction { } in the then: block like below:
Java Code:
// legacy code (still running on EJB 1.0 framework, and no dependency injection involved)
// can't alter java code base
public voidGetData() {
DataService ds = new DataService();
ds = ds.findByOffset(5);
Long len = ds.getOffset() // happy path scenario; missing a null check
// other code
}
// other varieties of same code:
public voidGetData2() {
ItemEJB tmpItem = new ItemEJB();
ItemEJB item = tmpItem.findByOffset(5);
if(null != item) {
Long len = item.getOffset();
// other code
}
}
public voidGetData3() {
ItemEJB item = new ItemEJB().findByOffset(5);
if(null != item) {
Long len = item.getOffset();
// other code
}
}
Spock Test:
def "test scene1"() {
given: "a task"
// other code ommitted
DataService mockObj = Mock(DataService)
when: "take action"
// code omitted
then: "action response"
interaction {
verifyNoDataScenario() // How to add verifyErrorScenario() interaction to the list?
}
}
private verifyDataScenario() {
1 * mockObj.findByOffset(5) >> mockObj // the findByOffset() returns an object, so mapped to same mock instance
1 * mockObj.getOffset() >> 200
}
private verifyErrorScenario() {
1 * mockObj.findByOffset(5) >> null // the findByOffset() returns null
0 * mockObj.getOffset() >> 200 // this won't be executed, and should ie expected to throw NPE
}
The interaction closure doesn't accept more than one method call. I'm not sure if it's design limitation. I believe more can be done in the closure than just mentioning the method name. I also tried interpolating the mockObj as a variable and use data pipe / data table, but since it's referring the same mock instance, it's not working. I'll post that as a separate question.
I ended up repeating the test case twice just to invoke different interaction methods. Down the line I see more scenarios, and wanted to avoid copy & paste approach. Appreciate any pointers to achieve this.
Update:
Modified shared java code as the earlier DataService name was confusing.
As there's no DI involved, and I didn't find a way to mock method variables, so I mock them using PowerMockito, e.g. PowerMockito.whenNew(DataService.class).withNoArguments().thenReturn(mockObj)
Your application code looks very strange. Is the programming style in your legacy application really that bad? First a DataService object is created with a no-arguments constructor, just to be overwritten in the next step by calling a method on that instance which again returns a DataService object. What kind of programmer creates code like that? Or did you just make up some pseudo code which does not have much in common with your real application? Please explain.
As for your test code, it also does not make sense because you instantiate DataService mockObj as a local variable in your feature method (test method), which means that in your helper method mockObj cannot be accessed. So either you need to pass the object as a parameter to the helper methods or you need to make it a field in your test class.
Last, but not least, your local mock object is never injected into the class under test because, as I said in the first paragraph, the DataService object in getData() is also a local variable. Unless your application code is compeletely fake, there is no way to inject the mock because getData() does not have any method parameter and the DataService object is not a field which could be set via setter method or constructor. Thus, you can create as many mocks as you want, the application will never have any knowledge of them. So your stubbing findByOffset(long offset) (why don't you show the code of that method?) has no effect whatsoever.
Bottom line: Please provide an example reflecting the structure of your real code, both application and test code. The snippets you provide do not make any sense, unfortunately. I am trying to help, but like this I cannot.
Update:
In my comments I mentioned refactoring your legacy code for testability by adding a constructor, setter method or an overloaded getData method with an additional parameter. Here is an example of what I mean:
Dummy helper class:
package de.scrum_master.stackoverflow.q58470315;
public class DataService {
private long offset;
public DataService(long offset) {
this.offset = offset;
}
public DataService() {}
public DataService findByOffset(long offset) {
return new DataService(offset);
}
public long getOffset() {
return offset;
}
#Override
public String toString() {
return "DataService{" +
"offset=" + offset +
'}';
}
}
Subject under test:
Let me add a private DataService member with a setter in order to make the object injectable. I am also adding a check if the ds member has been injected or not. If not, the code will behave like before in production and create a new object by itself.
package de.scrum_master.stackoverflow.q58470315;
public class ToBeTestedWithInteractions {
private DataService ds;
public void setDataService(DataService ds) {
this.ds = ds;
}
// legacy code; can't alter
public void getData() {
if (ds == null)
ds = new DataService();
ds = ds.findByOffset(5);
Long len = ds.getOffset();
}
}
Spock test:
Now let us test both the normal and the error scenario. Actually I think you should break it down into two smaller feature methods, but as you seem to wish to test everything (IMO too much) in one method, you can also do that via two distinct pairs of when-then blocks. You do not need to explicitly declare any interaction blocks in order to do so.
package de.scrum_master.stackoverflow.q58470315
import spock.lang.Specification
class RepeatedInteractionsTest extends Specification {
def "test scene1"() {
given: "subject under test with injected mock"
ToBeTestedWithInteractions subjectUnderTest = new ToBeTestedWithInteractions()
DataService dataService = Mock()
subjectUnderTest.dataService = dataService
when: "getting data"
subjectUnderTest.getData()
then: "no error, normal return values"
noExceptionThrown()
1 * dataService.findByOffset(5) >> dataService
1 * dataService.getOffset() >> 200
when: "getting data"
subjectUnderTest.getData()
then: "NPE, only first method called"
thrown NullPointerException
1 * dataService.findByOffset(5) >> null
0 * dataService.getOffset()
}
}
Please also note that testing for exceptions thrown or not thrown adds value to the test, the interaction testing just checks internal legacy code behaviour, which has little to no value.
Moving from Ember 1.5.1 to 1.6.0, I've run into an issue with __nextSuper (which has been changing in the last few versions). You can see the offending code here.
And here's the relevant Ember code:
function wrap(func, superFunc) {
function superWrapper() {
var ret, sup = this.__nextSuper; // THIS LINE
this.__nextSuper = superFunc;
ret = apply(this, func, arguments);
this.__nextSuper = sup;
return ret;
}
superWrapper.wrappedFunction = func;
superWrapper.wrappedFunction.__ember_arity__ = func.length;
superWrapper.__ember_observes__ = func.__ember_observes__;
superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
superWrapper.__ember_listens__ = func.__ember_listens__;
return superWrapper;
};
What happens is, at some point, the superWrapper function gets called with window as the this value. So when I reach the line marked above, this.__nextSuper comes out to be undefined. But rather than sup simply being undefined, it throws the following error:
TypeError: Cannot read property '__nextSuper' of undefined
The thing is, when I pause in the debugger, this is defined (it's the window object). And when I paste var ret, sup = this.__nextSuper; into the console, it works as expected. And, if I go up the stack frame and check the this value, it's exactly what I expect. So I have no idea why superWrapper suddenly has a bad this value.
Finally, the most interesting part, this only happens in the browser; it works fine in PhantomJS. The changelog didn't seem to list anything to do with __nextSuper as a breaking bugfix, but obviously something has changed. How can I solve this issue?
Ember 1.6 looks to have a requirement on super method being called from the scope of the object hosting the super method (probably a bug, but I'm not positive). In your case you'd want to keep track of the scope, then call the super method using it:
(scope is the object that houses isEqual)
var scope = meta.isEqual ? meta : this.get('store').attributeTypeFor(meta.type);
if (scope.isEqual(server, value)) { ...
instead of (scope is window and explodes in 1.6+)
var isEqual = meta.isEqual || this.get('store').attributeTypeFor(meta.type).isEqual;
if (isEqual(server, value)) { ...
Here's a super simple example showing the problem (1.6+): http://emberjs.jsbin.com/yelesahe/1/edit
And working in 1.5.1: http://emberjs.jsbin.com/zedevudo/1/edit
Issue: https://github.com/emberjs/ember.js/issues/5198
I'm just setting up some first unit tests, and I can't quite see how I'm trying to achieve (with my current test structure) can be done, which means I'm not sure whether my approach to the tests is incorrect, or it's just a limitation on xUnit.
I'm testing my MVC Controllers, and want to ensure that they all provide a ArgumentNullException if they are constructed passing null across as the arguments (they get resolved via Castle in the real world).
So, I've a private field on the Test class:
private IEnumerable<Type> ControllerTypes = typeof(MyBaseController).Assembly.GetTypes().Where(t => IsController(t));
Then, my test method:
[Fact]
public void EnsureControllersThrowIfProvidedWithNull() {
foreach (var controller in ControllerTypes) {
var ctrs = GetConstructorsForType(controller);
if (null == ctrs || !ctrs.Any()) { //if the controller has no constructors, that's fine, we just skip over it
continue;
}
var ctr = ctrs.ElementAt(0);
var ctrParamsAsNull = ctr.GetParameters().Select(p => (object)null);
Assert.Throws<ArgumentNullException>(() => {
ctr.Invoke(ctrParamsAsNull.ToArray());
});
}
}
So this is all working fine, I run the test runner, and one of my Controllers doesn't throw an ArgumentNullException when passed null, great, my test fails, but I don't know which controller it was, from the given output.
I do know how I can debug through the test to see which it is that fails, and can manually go through all my controllers to check which it is, but it would be useful to know which controller it was that failed.
Or am I just using a unit test wrong here?
(Side note, there's another test which ensures there's only 1 public constructor for each controller, so I can be sure I'm targeting the correct constructor when this fires, as long as that first test passed).
Thanks
Note:
There's a flaw in the logic for the test, which means it doesn't fully cover what I was expecting it too, as long as it throws an ArgumentNullException for at least 1 of the arguments, then it will pass the test, which isn't right. However as the arguments are interfaces I can't instantiate a new instance of them. So anyone looking to copy the code for the test, I wouldn't do so. Not looking for a solution to that issue here.
Assert.Throws is only helper method that executes delegate inside try catch block. You don't have to use it and you can replace it with your own implementation. Something like:
[Fact]
public void EnsureControllersThrowIfProvidedWithNull() {
foreach (var controller in ControllerTypes) {
var ctrs = GetConstructorsForType(controller);
if (null == ctrs || !ctrs.Any()) { //if the controller has no constructors, that's fine, we just skip over it
continue;
}
var ctr = ctrs.ElementAt(0);
var ctrParamsAsNull = ctr.GetParameters().Select(p => (object)null);
book ok = false;
try
{
ctr.Invoke(ctrParamsAsNull.ToArray());
}
catch(ArgumentNullException)
{
//you get exception you expected so continue
ok = true;
}
if(!ok)
{
// you didn't get exception so throw your own exception with message that contains controller type name
throw new Exception(String.Format("Ctor on type {0} did not throw ArgumentNullException",controller.Name);
}
}
}
This is only as idea to work on. You can refactor that inside your own static assertion method...
I am pulling my hair out with this one. I have looked and cannot find a simple, clear example of creating and using a partial stub with Microsoft Moles. Maybe I'm missing somethimg, or have my code architected poorly, but I can't seem to get this to work.
Here's my class (simplified):
public class AccountService : IAccountService {
private readonly webServiceProxy IExternalWebServiceProxy;
public AccountService(IExternalWebServiceProxy webServiceProxy) {
this.webServiceProxy = webServiceProxy;
}
public List<AccountModel> GetAccounts(string customerId) {
var returnList = new List<AccountModel>();
var xmlResponse = webServiceProxy.GetAllCustomerAccounts(customerId);
var accountNodes = xmlResponse.SelectNodes("//AccountNodes");
if (accountNodes != null)
{
foreach (XmlNode node in accountNodes)
{
var account = this.MapAccountFromXml(node);
if (!string.IsNullOrEmpty(account.AccountNumber))
{
returnList.Add(account);
}
}
}
return returnList;
}
public AccountModel MapAccountFromXml(XmlNode node) {
if (!IsValidAccount(node) {
return null;
}
// This performs a lot of XML manipulation getting nodes based on attributes
// and mapping them to the various properties of the AccountModel. It's messy
// and I didn't want it inline with the other code.
return populatedAccountModel;
{
public bool IsValidAccount(XmlNode node)
{
var taxSelectValue = node.SelectSingleNode("//FORMAT/Field[#taxSelect='1']").First().Value;
var accountStatus = // similar to first line in that it gets a single node using a specific XPath
var maturityDate = // similar to first line in that it gets a single node using a specific XPath
var maturityValue = // similar to first line in that it gets a single node using a specific XPath
return taxSelectValue != string.Empty && taxSelectValue != "0" && (accountStatusValue != "CL" || (maturityDate.Year >= DateTime.Now.AddYears(-1).Year));
}
}
What I want to do is test my GetAccounts() method. I can stub out the IExternalWebServiceProxy call and return fake XML, but I have internal calls happening in my service since my GetAccounts() method calls MapAccountFromXml() which in turn calls IsValidAccount().
Perhaps the solution is to not worry about breaking out the long and involved MapAccountFromXml() and IsValidAccount() code and just put them inline into the GetAccount() call, but I would rather leave them broken out for code readability.
I have my Moles assembly created, and know I can create a stub version of my class like this
var stubWebService = SIExternalWebServiceProxy {
GetAllCustomerAccounts = delegate {
return SomeHelper.GetFakeXmlDocument();
}
}
var stubAccountService = new SAccountService() { callsBase = true; }
My problem is I don't know how to then override the internal calls to MapAccountFromXml and IsValidAccount and I don't want my Unit Test to be testing thos methods, I'd like to isolate GetAccounts for the test. I read somewhere the methods need to be virtual to be overriden in a partial stub, but could not find anything that then showed how to create a stub that overrides a few methods while calling the base for the one I want to test.
Peer put me on the right track, thank you.
It turned out that what I was looking for is called Detours in Moles. Rather than stub an interface using
var stubAccountService = new SIAccountService();
what I needed to do was create an instance of my AccountService and then detour all calls to the methods I wanted to mock, like this
var accountService = new AccountService();
MAccountService.AllInstances.MapAccountFromXmlXmlNode = delegate {
return new AccountModel();
};
The MAccountService is provided by Moles when you Mole your assembly. The only missing piece to this is that for this to work you need to add the following attribute to your test method:
[HostType("Moles")]
This worked for me locally, but in the end I had trouble getting TFS to do automated builds
UPDATE
I just stumbled on another way of doing this, while looking at Rhino Mocks. If the methods in the class being mocked are virtual then you can override them in the mock, like this:
var accountService = new SAccountService();
accountService.MapAccountFromXmlXmlNode = delegate
{
return new AccountModel();
}
Now I can call
accountService.GetMemberAccounts();
and when accountService makes its call to MapAccountFromXml it will be caught by the stub and processed as I deem necessary. No messing with HostType and it works like a charm.
To test methods in you class in issolation you do this with moles by making a mole for the IsValidAccount and MapAccountFromXml methods. Or make a stub implementation with stubs where you let the stub call the orriginal methode using base. Or what I think is a nicer solution, make a test class which overrides the methods you do want to stub (this is the same what a stub would do, except you see all what is happening in your own code):
public class TestHelperAccountService : AccountService {
public override AccountModel MapAccountFromXml(XmlNode node) {
return new AccountModel(){
//Accountmodelstub
};
{
public override bool IsValidAccount(XmlNode node)
{
return true;
}
}
This way you can do your test for the GetAccount method on your TestHelperAccountService class where you GetAccount method runs in full issolation. You can do the same for the methods like MapAccountFromXml to test them seperatly.