unit testing - Maintainable mocks -



unit testing - Maintainable mocks -

mock objects introduce approach deep behavior testing of programme unit. should pass mocked dependency tested unit , check if works dependency should do.

let have 2 classes , b:

public class { private b b; public a(b b) { this.b = b; } public void dosomething() { b.performsomeaction(); if(b.state == special value) { b.performanotheraction(); } } } public class b { public bstate state { get; private set; } public void performsomeaction() { //some actions state = special value; } public void performanotheraction() { if(state != special value) { fail(); //for illustration throw new invalidoperationexception(); } } }

imagine class b beingness tested unit test testb.

to unit test class can either pass b it's constructor (to state based testing) or pass b's mock (to behavior based testing).

let have chosen sec approach (for illustration can't verify a's state straight , can indirectly) , created unit test testa (which doesn't contain reference b).

so introduce interface idependency , classes like:

public interface idependency { void performsomeaction(); void performanotheraction(); } public class { private idependency d; public a(idependency d) { this.d = d; } public void dosomething() { d.performsomeaction(); if(d.state == special value) { d.performanotheraction(); } } } public class b : idependency { public bstate state { get; private set; } public void performsomeaction() { //some actions state = special value; } public void performanotheraction() { if(state != special value) { fail(); //for illustration throw new invalidoperationexception(); } } }

and unit test testb similar to:

[testclass] public class testb { [testmethod] public void shouldperformanotheractionwhendependencyreturnssomespecialvalue() { var d = createdependencymocksuchthatitreturnssomespecialvalue(); var = createa(d.object); a.dosomething(); assertsomeactionwasperformedfordependency(d); } [testmethod] public void shouldnotperformanotheractionwhendependencyreturnssomenormalvalue() { var d = createdependencymocksuchthatitreturnssomenormalvalue(); var = createa(d.object); a.dosomething(); assertsomeactionwasnotperformedfordependency(d); } }

ok. it's happy moment developer - tested , tests green. good.

but!

when modifies logic of class b (for illustration modifies if(state != special value) if(state != value) ) testb fails.

this guy fixes test , thinks goes again.

but if seek pass b constructor of a.dosomething fail.

the root cause of our mock object. fixed old behavior of b object. when b changed behavior mock didn't reflect it.

so, question how create mock of b follow changes of behavior of b?

this question of viewpoint. normally, mock interface, not concrete class. in example, b's mock implementation of idependency, b. b's mock must alter whenever behaviour of idependency changes, , can ensure looking @ implementations of idependency when alter defined behaviour of idependency.

so, enforcement through 2 simple rules ought followed in code base:

when class implements interface, must fulfill defined behaviour of interface after modification. when alter interface, must adapt implementers fulfill new interface.

ideally, have unit tests in place test against defined behaviour of idependency, apply both b , bmock , grab violations of these rules.

unit-testing mocking maintainability

Comments

Popular posts from this blog

web services - java.lang.NoClassDefFoundError: Could not initialize class net.sf.cglib.proxy.Enhancer -

Accessing MATLAB's unicode strings from C -

javascript - mongodb won't find my schema method in nested container -