I am trying to create a test in grails to ensure indeed that the unique:true constraint works, here's my class and test file:
package edu.drexel.goodwin.events.domain
class UpayConfig {
String name
String siteId
String postingCode
static constraints = {
name(blank:false, maxSize:50)
siteId(blank:false, unique:true)
postingCode(blank:false)
}
}
package edu.drexel.goodwin.events.domain
import grails.test.*
class UpayConfigTests extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
}
protected void tearDown() {
super.tearDown()
}
void testCleanUpayConfigValidates() {
mockForConstraintsTests UpayConfig
def cleanUpayConfig = create()
assertTrue cleanUpayConfig.validate()
}
void testUpayConfigSiteIdMustBeUnique() {
mockForConstraintsTests UpayConfig
def upayConfigOne = create()
def upayConfigTwo = create()
assertFalse upayConfigOne.validate()
assertFalse upayConfigTwo.validate()
upayConfigTwo.siteId = '81'
assertTrue upayConfigOne.validate()
assertTrue upayConfigTwo.validate()
}
UpayConfig create() {
def upayConfig = new UpayConfig(
siteId: '82',
name: 'SMT - Workshops',
postingCode: '6'
)
}
}
But that second test fails, the upayConfig variables both return true for .validate() even though I am telling them both to have the same siteId...
I have a feeling this has something to do with the fact that these aren't being placed in the database, just being stored in memory?
All help is much appreciated, thank you.
-Asaf
The uniqueness will be at the database level. You're never saving the domain, so as far as upayConfigTwo is concerned, it is unique. You'll need to do a regular mock and actually call save() on upayConfigOne.
Thank you. I looked up this website: http://www.ibm.com/developerworks/java/library/j-grails10209/index.html and it had a section called "Testing the unique constraint with mockForConstraintsTests()" so following it I modified my test to be as follows and it passed correctly:
void testUpayConfigSiteIdMustBeUnique() {
def upayConfigOne = create()
mockForConstraintsTests(UpayConfig, [upayConfigOne])
def upayConfigTwo = create()
assertFalse upayConfigTwo.validate()
assertEquals "unique", upayConfigTwo.errors["siteId"]
upayConfigTwo.siteId = '81'
assertTrue upayConfigTwo.validate()
}
Thank you for your help,
-Asaf
Related
I'm trying to translate a ParameterizedTest from JUnit4 to JUnit5 (sadly I'm not particularly skilled in testing).
In JUnit4 I have the following class:
#RunWith(Parameterized.class)
public class AssertionTestCase {
private final TestInput testInput;
public AssertionTestCase(TestInput testInput) {
this.testInput = testInput;
}
#Parameterized.Parameters
public static Collection<Object[]> data() {
return AssertionTestCaseDataProvider.createDataCase();
}
#Test(timeout = 15 * 60 * 1000L)
public void testDailyAssertion() {
LOG.info("Testing input {}/{}", testInput.getTestCase(), testInput.getTestName());
//assert stuffs
}
}
in the AssertionTestCaseDataProvider class I have a simple method generating a collection of Object[]:
class AssertionTestCaseDataProvider {
static Collection<Object[]> createDataCase() {
final List<TestInput> testInputs = new ArrayList<>();
//create and populate testInputs
return testInputs.stream()
.map(testInput -> new Object[]{testInput})
.collect(Collectors.toList());
}
}
I've been trying to translate it using JUnit5 and obtained this:
class AssertionTestCase {
private final TestInput testInput;
public AssertionTestCase(TestInput testInput) {
this.testInput = testInput;
}
public static Collection<Object[]> data() {
return AssertionTestCaseDataProvider.createDataCase();
}
#ParameterizedTest
#MethodSource("data")
void testDailyAssertion() {
LOG.info("Testing input {}/{}", testInput.getTestCase(), testInput.getTestName());
// assert stuffs
}
}
I did not apply any change to the AssertionTestCaseDataProvider class.
Nevertheless, I'm getting the following error:
No ParameterResolver registered for parameter [com.xxx.xx.xxx.xxx.testinput.TestInput arg0] in constructor [public `com.xxx.xxx.xxx.xxx.xxx.AssertionTestCase(com.xxx.xxx.xxx.xxx.testinput.TestInput)]. org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [com.xxx.xx.xxx.xxx.testinput.TestInput arg0] in constructor [public com.xxx.xxx.xxx.xxx.xxx.AssertionTestCase(com.xxx.xxx.xxx.xxx.testinput.TestInput)].`
I understand I'm probably not applying correctly JUnit5 when initializing the input collection for the test. Am I missing some annotations?
I've also tried to use #ArgumentSource instead of #MethodSource and implementing Argument for AssertionTestCaseDataProvider, with the same failing results.
It works in a bit another way in Junit5.
Test Method should have parameters, and provider method should return a Stream.
static Stream<Arguments> data(){
return Stream.of(
Arguments.of("a", 1),
Arguments.of("d", 2)
);
}
#ParameterizedTest
#MethodSource("data")
void testDailyAssertion(String a, int b) {
Assertions.assertAll(
() -> Assertions.assertEquals("a", a),
() -> Assertions.assertEquals(1, b)
);
}
In your case you can just return a Stream<TestInput>:
static Stream<TestInput> createDataCase() {
final List<TestInput> testInputs = new ArrayList<>();
//create and populate testInputs
return testInputs.stream();
}
and then in your testMethod:
#ParameterizedTest
#MethodSource("createDataCase")
void testDailyAssertion(TestInput testInput) {
{your assertions}
}
I am very new to TDD. I am using phpunit 7.4x-dev. I have the following abstract class that I am trying to develop unit tests for.
use PDO;
abstract class Model {
protected static function getDB() {
static $db = null;
if ($db === null) {
$db = new PDO(ConfigDatabase::DSN, ConfigDatabase::USER, ConfigDatabase::PASSWORD);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return $db;
}
}
I have created the following test to get around the need to deal with the static protected method. And it works if I provide "ConfigureDatabase" class.
use PHPUnit\Framework\TestCase;
class ModelTest extends TestCase {
function newMockClass(){
$stub = new class() extends Model{
function getStaticMethod($methodName){
return self::$methodName();
}
};
return $stub;
}
public function testDatabaseExists() {
$stub = $this->newMockClass();
$db = $stub->getStaticMethod('getDB');
$this->assertInstanceOf(PDO::class,$db);
}
}
Since I do not want my tests to rely on any actual database, How would I fake the calls to PDO.
Following Dormilich suggestion I developed a database interface, just in case I decide later I do not want to use PDO.
interface CRUDImp {
function __construct($datbaseBridgeLikePDO);
...
}
Next I wrote my tests for the constructor. I used setup to make sure I was starting with a fresh mock of \PDO.
class PDOWrapperTest extends TestCase {
private $pdoMock;
private $db;
function setup() {
$this->pdoMock = $this->createMock('\PDO');
$this->db = new PDOWrapper($this->pdoMock);
}
public function testWrapperExists() {
$this->pdoMock->method('getAttribute')->willReturn(\PDO::ERRMODE_EXCEPTION);
$db = new PDOWrapper($this->pdoMock);
$x = $db instanceof CRUDImp;
$this->assertTrue($x);
}
/**
* #expectedException \Exception
*/
public function testNonPDOPassedToConstructor() {
$mock = $this->createMock('\Exception');
$x = new PDOWrapper($mock);
}
...
}
Since PHP is loosely typed I check to make sure that the class passed to the constructor was an instance of \PDO. I implemented the concrete class as follows
class PDOWrapper implements CRUDImp {
private $pdo;
private $dataOutputType = \PDO::FETCH_ASSOC;
public function __construct($pdo) {
if (!($pdo instanceof \PDO)) {
throw new \Exception("PDOWrapper must be passed instance of \PDO");
}
$attr_Errmode = $pdo->getAttribute(\PDO::ATTR_ERRMODE);
if ($attr_Errmode !== \PDO::ERRMODE_EXCEPTION) {
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
}
$this->pdo = $pdo;
}
...
}
Now that I have an independent database wrapper the original Model tests are at the moment trivial and no longer needed. The abstract class Model was modified as follows:
abstract class Model {
protected $database=null;
function __construct(CRUDWrapper $database) {
$this->database = $database;
}
...
}
So for those not familiar with dependency injection I found the following links helpful:
http://php-di.org/doc/understanding-di.html
https://codeinphp.github.io/post/dependency-injection-in-php/
https://designpatternsphp.readthedocs.io/en/latest/Structural/DependencyInjection/README.html
Hope this shortens someone's work.
I'm trying to test small pieces of code. I do not want test one of the method and used Mockito.doNothing(), but this method was still run. How can I do that?
protected EncoderClientCommandEventHandler clientCommandEventHandlerProcessStop = new EncoderClientCommand.EncoderClientCommandEventHandler() {
#Override
public void onCommandPerformed(
EncoderClientCommand clientCommand) {
setWatcherActivated(false);
buttonsBackToNormal();
}
};
protected void processStop() {
EncoderServerCommand serverCommand = new EncoderServerCommand();
serverCommand.setAction(EncoderAction.STOP);
checkAndSetExtension();
serverCommand.setKey(getArchiveJobKey());
getCommandFacade().performCommand(
serverCommand,
EncoderClientCommand.getType(),
clientCommandEventHandlerProcessStop);
}
#Test
public void testClientCommandEventHandlerProcessStop() {
EncoderClientCommand encoderClientCommand = mock(EncoderClientCommand.class);
Mockito.doNothing().when(encoderCompositeSpy).buttonsBackToNormal();
when(encoderCompositeSpy.isWatcherActivated()).thenReturn(false);
encoderCompositeSpy.clientCommandEventHandlerProcessStop.onCommandPerformed(encoderClientCommand);
I've found the problem. One of the variable is already mocked in buttonsBackNormal().
I have a
class A {
public static boolean isRunning() {
if (ctx == null) { .. }
return ctx.isRunning();
}
}
I am testing a method that in the middle calls A.isRunning();
class B {
public void methodToBeTested() {
A.isRunning();
// do somthing
}
}
I want to test this in a way that when A.isRunning() is called it right away returns true and does not go initializing the context.
As class B does not have a property for type A, I am not sure what is the way to test this method?
Thanks
You can redefine your A.isRunning() through metaprogramming:
A.metaClass.static.isRunning = { true }
If you run that line before your test, it will make that method always return true
The following TestNG (6.3) test case generates the error "Invalid context for the recording of expectations"
#Listeners({ Initializer.class })
public final class ClassUnderTestTest {
private ClassUnderTest cut;
#SuppressWarnings("unused")
#BeforeMethod
private void initialise() {
cut = new ClassUnderTest();
}
#Test
public void doSomething() {
new Expectations() {
MockedClass tmc;
{
tmc.doMethod("Hello"); result = "Hello";
}
};
String result = cut.doSomething();
assertEquals(result, "Hello");
}
}
The class under test is below.
public class ClassUnderTest {
MockedClass service = new MockedClass();
MockedInterface ifce = new MockedInterfaceImpl();
public String doSomething() {
return (String) service.doMethod("Hello");
}
public String doSomethingElse() {
return (String) ifce.testMethod("Hello again");
}
}
I am making the assumption that because I am using the #Listeners annotation that I do not require the javaagent command line argument. This assumption may be wrong....
Can anyone point out what I have missed?
The JMockit-TestNG Initializer must run once for the whole test run, so using #Listeners on individual test classes won't work.
Instead, simply upgrade to JMockit 0.999.11, which works transparently with TestNG 6.2+, without any need to specify a listener or the -javaagent parameter (unless running on JDK 1.5).