I have a static method with ref parameters in my legacy (untestable) dll. I am trying to write unit tests for a class that calls into this method.
public static class Branding
{
...
...
static public bool GetBranding(Int32 providerId,
Int32 employerId,
string brandingElement,
ref string brandingValue)
...
...
}
I need help writing a shim statement for this call
ShimBranding.GetBrandingInt32Int32StringStringRef =
( providerId, employerId, element, { ====> WHAT GOES HERE <===== } )
=>
true;
Thanks!
using (ShimsContext.Create())
{
ShimBranding.GetBrandingInt32Int32StringStringRef =
(int providerId, int employerId, string brandingElement, ref string brandingValue) =>
{
brandingValue = "Blah";
return true;
};
}
Related
With mockito-inline how to test static function (with stubbing other static function), or mock/stub some internal depended class?
Here is the sample:
Having a class Util which internally depending on java.security.MessageDigest
package java.security;
public abstract class MessageDigest extends MessageDigestSpi
... ...
public byte[] digest() {
byte[] result = engineDigest();
return result;
}
}
and the container class has a few static functions to be tested
public class Util {
public static byte[] getStringDigest(#NonNull String text, #NonNull String algorithm, #NonNull String charSet) {
if (text == null) {
return null;
}
MessageDigest messageDigest; //<== depend on
try {
messageDigest = MessageDigest.getInstance(algorithm);
messageDigest.update(text.getBytes(charSet));
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
return null;
}
return messageDigest.digest();
}
public static String generateId(#NonNull String s) {
byte[] sha1Byte = getStringDigest(s, "SHA-1", "UTF-8");
if (sha1Byte == null) {
return s;
}
// otherwise build the id
String id = buildId(sha1Byte);
return id;
}
}
would like to test the Utils.generateId(#NonNull String s) with stubbing getStringDigest() returning null, so that sometext is expected to return.
since it is static function so it was tested with powermock.
#Test
public test_util_1{
PowerMockito.mockStatic(MessageDigest.class);
String sometext = "sometext";
PowerMockito.when(Util.getStringDigest(sometext, "SHA-1", "UTF-8")).thenReturn(null);
assertEquals(sometext, Util.generateId(sometext));
}
with mock stub, when Util.getStringDigest() is called null is returned.
It worked fine.
now the mockito-inline supports testing static function (and it has problem to mix with powermockito2 when testing kotlin etc.) so the powermock is removed.
Tried with mockito-inline 3.8.0
#Test
public void test_util_1() {
String sometext = "sometext";
try (MockedStatic<Util> utilMoc = Mockito.mockStatic(Util.class)) {
utilMoc.when(() -> Util.getStringDigest(sometext, "SHA-1", "UTF-8"))
.thenReturn(null);
assertEquals(sometext, Util.generateId(sometext));
}
got error:
java.lang.AssertionError: Unexpected value
Expected :sometext
Actual :null
the Util.generateId(sometext) returns null (not the sometext).
when using assertEquals(sometext, sutilMoc.generateId(sometext)); it cannt compile and says cannt resolve the generateId().
How to use mockito-inline to test the static function?
Or if there is way to mock/stub the depended abstract class MessageDigest for stub the digest() to return null, but dont know is it possible?
found a way to make the test work (using .thenCallRealMethod()),
but still not find a way to mock the depended class which is instantiated inside the static function. if anyone knows a solution for that?
#Test
public void test_util_1() {
String sometext = "sometext";
try (MockedStatic<Util> utilMoc = Mockito.mockStatic(Util.class)) {
utilMoc.when(() -> Util.getStringDigest(anyString(), anyString(), anyString()))
.thenReturn(null);
// need to tell mock to call the original, otherwise a default mocked stub will be called
utilMoc.when(() -> Util.generateId(anyString()))
.thenCallRealMethod();
assertEquals(sometext, Util.generateId(sometext));
}
In the code Google Mock test snippet there is an EXPECT_CALL that returns True and an argument reference for 200 times.
How can I let the test only return True every nth time. For example return True each 10th call and otherwise return False.
class MockHandler : public Handler
{
public:
MOCK_METHOD1(RxMsg, bool(Msg &msg));
}
TEST(TestDispatcher, HandlePing)
{
auto mockedHandler = make_unique<MockHandler>();
Msg rxMsg = { REQUEST::REQ_PING, sizeof(DefaultMsg_t), rxMsg.rx,(uint8_t*)"0"};
EXPECT_CALL(*mockedHandler,
RxMsg(_)).Times(checkValue).WillRepeatedly(
DoAll(SetArgReferee<0>(rxMsg), Return(TRUE)));
Dispatcher dispatcher(10, mockedHandler);
for (int i = 0; i < 199; i++)
{
dispatcher.RunToCompletion();
}
}
There are few approaches that might work for you. I like the solution with Invoke as a default action, because it is the most flexible. You didn't provide mcve in your question, so I wrote very simple implementations for the classes you use. Also you made a mistake using unique_ptr for the mock. In 99% of cases is must be shared_ptr, because you are sharing it between testing environment and your System Under Test.
class Msg {};
class Handler {
public:
virtual bool RxMsg(Msg &msg) = 0;
};
class MockHandler: public Handler
{
public:
MOCK_METHOD1(RxMsg, bool(Msg &msg));
};
class Dispatcher {
public:
Dispatcher(std::shared_ptr<Handler> handler): h_(handler) {}
void run() {
Msg m;
std::cout << h_->RxMsg(m) << std::endl;
}
private:
std::shared_ptr<Handler> h_;
};
class MyFixture: public ::testing::Test {
protected:
MyFixture(): mockCallCounter_(0) {
mockHandler_.reset(new MockHandler);
sut_.reset(new Dispatcher(mockHandler_));
}
void configureMock(int period) {
ON_CALL(*mockHandler_, RxMsg(_)).WillByDefault(Invoke(
[this, period](Msg &msg) {
// you can also set the output arg here
// msg = something;
if ((mockCallCounter_++ % period) == 0) {
return true;
}
return false;
}));
}
int mockCallCounter_;
std::shared_ptr<MockHandler> mockHandler_;
std::unique_ptr<Dispatcher> sut_;
};
TEST_F(MyFixture, HandlePing) {
configureMock(10);
for (int i = 0; i < 199; i++) {
sut_->run();
}
}
At the beginning of each test you should call configureMock method that will Invoke ON_CALL macro setting the default action for your mock. Function passed to Invoke can be any function matching the signature of the method you are overwriting. In this case it;s a function that counts how many times mock has already been called and returns appropriate value. You can also assign some particular object to the msg output argument.
I am using JDBI 3 and have written the following utility function.
public class JdbiHelper {
// ...
public <T, DAO> T fetch(final Function<DAO, T> function, Class<DAO> daoClass) {
return dbi.withHandle(handle -> {
final DAO dao = handle.attach(daoClass);
try {
return function.apply(dao);
}
finally {
handle.close();
}
});
}
}
which I can call in methods like this
public Optional<Account> findByEmailAddress(final String emailAddress) {
if (!exists(emailAddress))
return Optional.empty();
return jdbiHelper.fetch(dao -> ofNullable(dao.selectByEmailAddress(emailAddress)), AccountDAO.class);
}
private boolean exists(final String emailAddress) {
return jdbiHelper.fetch(dao -> dao.count(emailAddress) > 0, AccountDAO.class);
}
I am trying to write a test for the findByEmailAddress mocking jdbiHelper using Mockito 2 but cannot work out how to mock the dao -> part of the method.
I've tried using jdbiHelper.fetch(any(Function.class), eq(AccountDAO.class)) but as there are two different expectations of what to return it fails trying to cast one or the other.
Passing in a mocked Function causes a NPE as the dao param is null.
I have this Java test with Mockito:
public class PersistentNodeDeserializerTests {
#Test
public void userInfoPersistentNodeDeserializer() {
PersistentNode node = mock(PersistentNode.class);
when(node.stringChild("username")).thenReturn("cliff12");
//more stuff
}
}
PersistentNode is a Kotlin class:
open class PersistentNode(private val path: PersistentNodePath, val content: Any) {
val stringPath: String
get() = path.get()
val key: String
get() {
val parts = stringPath.split("/");
return parts[parts.size - 1];
}
val mapContent: Map<String, Any>
get() {
return content as HashMap<String, Any>
}
fun stringChild(child: String): String {
return mapContent.get(child) as String
}
}
I get this error:
kotlin.TypeCastException: null cannot be cast to non-null type
java.util.HashMap
How can I mock the property stringChild properly?
this library may solve your issue https://github.com/nhaarman/mockito-kotlin
EDIT: sorry, didn't realize you were using a Java test. If it's an option, try writing your test in kotlin too
I am using Microsoft Fakes framework within VS2012.
I use the following code to shim instance methods of my type.
using (ShimsContext.Create())
{
ShimDateTime.NowGet = () => { return new DateTime(1949, 10, 1); };
DateTime now = DateTime.Now; // shim works for the static property DateTime.Now.
Class1 dependency = new Class1();
using (ShimsContext.Create())
{
ShimClass1 shim1 = new ShimClass1();
StubClass1 stub1 = new StubClass1();
shim1.method1 = () => { return "shim method1"; };
shim1.IMethod1 = () => { return "shim IMethod1"; };
String s1 = dependency.method1();// shim doesn't work for the instance method.
String s2 = dependency.IMethod1();// shim doesn't work for the instance method.
}
The class1 and looks like this:
public class Class1 : Interface1
{
public String method1()
{
return "real method1";
}
//Interface 1 member
public string IMethod1()
{
return "real IMethod1";
}
}
I expect the s1 and s2 to be the shimed output, but it is still real output.
Why?
If 'method1' was static your shim would have worked. However with the current code you have not really shimmed out 'method1'. You need to either associate the instance with the shim instance
Class1 dependency = new ShimClass1() { Method1 = () => { return "Shim.Method1"; } };
or associate all instance methods with your delegate
ShimClass1.AllInstances.Method1 = (q)=> { return "Shim.Method1"; };
Also I dont see the need to have the ShimsContext.Create() done twice
If you want to use stubs to redirect IMethod1 you should be consuming the StubInterface1 instead
Class1 dependency = new StubInterface1() { Method1 = () { return ""; } };
Variations of these are available on msdn for reference