Apex Test Class - testing

newbie here...thanks for your patience. I'm interested in writing a test class for the following controller, but not sure where to begin:
public class savecontroller
{
private final Emp__c emps;
public savecontroller(ApexPages.StandardController controller)
{
this.emps= (Emp__c)controller.getRecord();
}
public void autosave()
{
upsert emps;
}
}
Thank you

Your code is a little bit strange... From this part:
public savecontroller(ApexPages.StandardController controller)
it looks like your controller is not really a "controller", but more like an extension of a standard controller for Emp__c object. I know, it doesn't affect anythingin your post (except maybe semantics), BUT (!) it does have an affect on how you write your test class. Since this is an extension, test class would look something like this:
#isTest
public class saveconttroller_test {
public static Emp__c test_emp; // declaration
static {
test_emp = new Emp__c();
insert test_emp; //since you have upsert you can leave this out
}
static testMethod void testsavecotroller() {
Test.startTest();
//in the next two lines we contruct standard controller and the extension
ApexPages.StandardController sc = new ApexPages.StandardController(test_emp);
savecontroller ext = new savecontroller(sc);
ext.autosave();
Test.stopTest();
}
}
Now, let me point out a few things... first, as I'm sure you know, test should cover as much code as possible. SF requires 75%, but the closer you get to 100% the better. But (!), you should always include something to assert if your method is doing what it is suppose to be doing. For example in your case, i would change method autosave() like this:
public PageReference autosave()
{
try {
upsert emps;
return new ApexPages.StandardController(test_emp).view();
} catch(Exception e) {
return null;
}
}
By doing so, you can include System.assertEquals(ref1, ref2); in your test class, wher ref1 is reference you would expect (if the upsertion was successful this would be test_emp page reference) and ref2 would be the reference you actually get from the test.
Second thing is using static method in the test. Whatever you write in this method will always execute on Test.startTest(); call.
Hope this helps you! :)
Cheers, G.

Related

How to create a BaseClass that adds logging messages

I am using serenity BDD for my automation testing and Page Object Model for my framework. I have created a BasePage class which will be inherited by all the other Pages. I want to minimize the logging messages from the Pages by adding all the log.info messages to a central Base page. Example, when calling the click() method, I will log before click and after click methods as shown below in the basePage class:
public class BasePage extends PageObject{
private static final Logger log = LogManager.getLogger(BasePage.class.getClass());
private final WebElementFacade element;
public static void clickBtn(WebElementFacade btnName) {
log.info("About to click " + btnName + " button");
btnName.click();
log.info("Successfully clicked on " + btnName + " button.");
}
Later I figured that instead of individually trying to figure out in advance what actions the user will perform on the webElements, and write new methods for each action (like the one shown above), just implement WebDriverFacade interface, so that I get all the unimplemented method list in BasePage from WebDriverFacade and then write the log messages inside each of them, like so:
public class BasePage extends PageObject implements WebElementFacade{
private static final Logger log = LogManager.getLogger(BasePage.class.getClass());
private final WebElementFacade element;
#Override
public void submit() {
// TODO Auto-generated method stub
}
#Override
public void sendKeys(CharSequence... keysToSend) {
// TODO Auto-generated method stub
}
#Override
public String getTagName() {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean isSelected() {
// TODO Auto-generated method stub
return false;
}
.
.
.
.
.
}
This will serve two purposes:
I will not have to create new methods for every action in BasePage class, example the 'clickBtn()' function in the first code
As I mentioned before, I will not have to figure out what method any other person who adds methods to my code might use and having to change the BasePage class to create the new actions. So basically less maintenance in the long run.
The problem I am facing is an error that I receive in the second use case:
The return types are incompatible for the inherited methods WebElementFacade.withTimeoutOf(int, TimeUnit), PageObject.withTimeoutOf(int, TimeUnit)
Now my question is:
How can solve this problem?
Is this the right way to do things or should I be going with the first method and have maintenance overhead.
Just figured that another scenario where this might be useful. To make sure that subclass methods do not use methods from pageObject and are forced to use the methods from BaseClass only. This can be done by wrapping the WebElementFacade and adding the log messages as an added functionality. Any thought on this would be appreciated.
Thank you!
Honestly it is a neat trick and if you get it working you should be proud.
I think I figured something similar out in a dynamic language.
But you are better off just adding the logging entries and learning the following.
How to name functions so you don't feel like they need renaming.
How to log clearly for debugging use.
This is because loggings power is in its flexibility.
When you learn how to dump something complex like a matrix so you can eye it and go uh-oh you are increasing your overall skills.
I apologize for not giving you code but I felt some "chase the other rabbit" advice was better.

Running DropwizardAppRule before each test in a class using junit

I have a test class that has several tests. At the moment I have this to start up the server, wipe the database etc:
#ClassRule
public static final DropwizardAppRule<ServiceConfig> RULE =
new DropwizardAppRule<ServiceConfig>(ServiceApp.class, ResourceHelpers.resourceFilePath("config.yml"));
All my tests work with this individually. But when I run them all together some fail since other tests modify data. I tried doing the following but I'm getting null pointers when calling RULE.getPort():
#ClassRule
public static DropwizardAppRule<ServiceConfig> RULE;
#Before
public void beforeClass() {
RULE = new DropwizardAppRule<ServiceConfig>(ServiceApp.class, ResourceHelpers.resourceFilePath("config.yml"));
}
I would have expected this to work but it doesn't seem to set the values of RULE properly. Any ideas?
Hi,
I don't know how to handle db "from within" DropwizardAppRule, so I may not really answer your question... I'm actually having another issue myself trying with DropwizardAppRule not properly being setup and torn down between tests. (So if you made progress going this way I'd like you insights).
Anyway, I think you need to handle your DB outside DropwizardAppRule and give it in the Rule. We resolved DB clearing by relying on custom and external TestsRules:
public class CockpitApplicationRule implements TestRule {
public static class App extends CockpitApplication<CockpitConfiguration> {
// only needed because of generics
}
public final DropwizardAppRule<CockpitConfiguration> dw;
public final EmbeddedDatabaseRule db;
public CockpitApplicationRule(String config, ConfigOverride... configOverrides) {
this.db = EmbeddedDatabaseRule.builder()
.initializedByPlugin(LiquibaseInitializer.builder().withChangelogResource("migrations.xml").build())
.build();
this.dw = new DropwizardAppRule<>(App.class, ResourceHelpers.resourceFilePath(config),
ConfigOverride.config("database.url", () -> this.db.getConnectionJdbcUrl()));
}
#Override
#Nullable
public Statement apply(#Nullable Statement base, #Nullable Description description) {
assert base != null;
assert description != null;
return RulesHelper.chain(base, description, dw, RulesHelper.dropDbAfter(db), db);
}
public DSLContext db() {
return DSL.using(db.getConnectionJdbcUrl());
}
}
Basically we override TestRule apply(...) to chain custom Statements. There's our RulesHelper if you want to take a look. That way the DB is cleanly handled by the Rules, we can fill our test DB in test classes using #Before setup methods.
org.zapodot.junit.db.EmbeddedDatabaseRule Is an external dependency that allows us to rather easily instantiate a DB for our tests.
The RulesHelper.dropDbAfter does the actual cleaning:
public static TestRule dropDbAfter(EmbeddedDatabaseRule db) {
return after(() -> DSL.using(db.getConnectionJdbcUrl()).execute("DROP ALL OBJECTS"));
}
You should be able to setup and clean the DB from #Before and #After methods without fully using TestRules though, but I'm not sure it's really easier in the end.
Hope this helped !

How to disable static initializer?

Assuming my system under test looks like this:
public class SysUnderTest {
public int foo() {
Trouble trouble1 = new Trouble();
Trouble trouble2 = new Trouble();
return trouble1.water(1) + trouble2.water(2);
}
}
The test will looks something like
public class DummyTest {
#Tested SysUnderTest sut;
#Mocked Trouble trouble;
#Test
public void testTrouble() {
new Expectations() {{
trouble.water(anyInt); returns(10, 20);
}};
assertThat("mocked result", sut.foo(), is(30));
new FullVerificationsInOrder() {{
Trouble t1 = new Trouble();
Trouble t2 = new Trouble();
t1.water(1);
t2.water(2);
}};
}
}
However, Trouble is actually a 3rd-party lib class that I have no control, which it does static initialization which will fail in testing env.
public class Trouble {
static {
troubleInitialize();
};
public int water(int i) {
return 0;
}
private static void troubleInitialize() {
throw new RuntimeException("Trouble");
}
}
I know I can use MockUp<Trouble> to get rid of the static initializer but I have no idea how to make use of it in case as I want to (in my realistic case) be able to distinguish the two new instances (created in SysUnderTest) and verify their invocations. I have tried different ways but all failed with some reasons
Adding a new MockUp<Trouble>(){#Mock void $clinit(){} }; in #Before/#BeforeClass, and keep #Mocked Trouble trouble;. It seems not working because the mockup action happens after the DummyTest class is loaded, which will load (unmodified) Trouble class which will throw exception during static initialization
Adding the new Mockup in a TestSuite and call the DummyTest in suite, similar problem as 1.
Simply put the behavior of returning 20, 30 in the fake class, and remove usage of Expectations/Verifications but I have no way to verify which instance is called with what parameter.
Is there a better way to solve my problem? Actually I would want to keep using Expectaitons/Verifications, all I want is some way to disable the static initializer during unit test.
Use stubOutClassInitialization to change the mocked class's static init to an empty method when using Mocked.
#Mocked(stubOutClassInitialization=true) Trouble trouble;

Inheriting ConstructorArguments in Ninject

I'm trying to find a method of passing a constructor argument to the constructors of child classes.
These objects are immutable so I'd prefer to use constructor arguments.
The issue I have encountered is that ConstructorArgument does not inherit to child instantiations and the following statements are not interchangeable:
_parsingProcessor = _kernel.Get<IParsingProcessor>(new ConstructorArgument("dataFilePath", dataFilePath);
and
_parsingProcessor = _kernel.Get<IParsingProcessor>(new Parameter("dataFilePath", dataFilePath, true);
So, how can get an inheritable ConstructorArgument and when does it makes sense, if ever, to new the Parameter class?
Yes, you can do this, but it's probably not what you really want. If the container is not actually responsible for instantiating its own dependencies, then its dependencies probably shouldn't be sharing its constructor arguments - it just doesn't make sense.
I'm pretty sure I know what you're trying to do, and the recommended approach is to create a unique binding specifically for your one container, and use the WhenInjectedInto conditional binding syntax, as in the example below:
public class Hello : IHello
{
private readonly string name;
public Hello(string name)
{
this.name = name;
}
public void SayHello()
{
Console.WriteLine("Hello, {0}!", name);
}
}
This is the class that takes a constructor argument which we want to modify, depending on who is asking for an IHello. Let's say it's this boring container class:
public class MyApp : IApp
{
private readonly IHello hello;
public MyApp(IHello hello)
{
this.hello = hello;
}
public virtual void Run()
{
hello.SayHello();
Console.ReadLine();
}
}
Now, here's how you do up the bindings:
public class MainModule : NinjectModule
{
public override void Load()
{
Bind<IApp>().To<MyApp>();
Bind<IHello>().To<Hello>()
.WithConstructorArgument("name", "Jim");
Bind<IHello>().To<Hello>()
.WhenInjectedInto<MyApp>()
.WithConstructorArgument("name", "Bob");
}
}
Basically all this binding is doing is saying the name should be "Jim" unless it's being requested by Hello, which in this case it is, so instead it will get the name "Bob".
If you are absolutely certain that you truly want cascading behaviour and understand that this is very dangerous and brittle, you can cheat using a method binding. Assuming that we've now added a name argument to the MyApp class for some unspecified purpose, the binding would be:
Bind<IHello>().ToMethod(ctx =>
ctx.Kernel.Get<Hello>(ctx.Request.ParentContext.Parameters
.OfType<ConstructorArgument>()
.Where(c => c.Name == "name")
.First()));
Please, please, make sure you are positive that this is what you want before doing it. It looks easy but it is also very likely to break during a simple refactoring, and 95% of the "customized dependency" scenarios I've seen can be addressed using the WhenInjectedInto binding instead.

Handling a C# method that isn't defined on a dynamic object (aka respond_to/method_missing)

Given the new dynamic support in C# 4, is it possible to write a class in such a way that if a method is invoked on an instance and that method is not present, dispatch is passed to another method? This might look something like:
public class Apple : ... {
// ...
private ... MethodMissing(string name, ...) {
if (name == "TurnIntoOrange") {
// do something
}
}
}
dynamic d = new Apple();
d.TurnIntoOrange(); // Not actually defined on Apple; will pass to MethodMissing.
Other languages would call this "method_missing support", under the more general heading of metaprogramming. I'm not sure what C# calls this specifically. But is it possible?
Absolutely. Either implement IDynamicMetaObjectProvider or derive from DynamicObject for a much simpler route. See the DLR documentation for some good examples.
Here's a quick example of DynamicObject:
using System;
using System.Dynamic;
public class MyDynamic : DynamicObject
{
public override bool TryInvokeMember
(InvokeMemberBinder binder,
object[] args,
out object result)
{
Console.WriteLine("I would have invoked: {0}",
binder.Name);
result = "dummy";
return true;
}
public string NormalMethod()
{
Console.WriteLine("In NormalMethod");
return "normal";
}
}
class Test
{
static void Main()
{
dynamic d = new MyDynamic();
Console.WriteLine(d.HelloWorld());
Console.WriteLine(d.NormalMethod());
}
}
<plug>
I have a bigger example of DynamicObject in the 2nd edition of C# in Depth but I haven't yet implemented IDyamicMetaObjectProvider. I'll do so before the book's release, but the early access edition only has the DynamicObject example at the moment. Btw, if you buy it today it's half price - use the code twtr0711. I'll edit this answer later on to remove that bit :)
</plug>