我正在使用Postgres(我认为与问题有关)和CakePHP 3。
我有以下单元测试,只是检查以确保模型可以保存有效的数据集。当我运行以下测试时,使用标准的“烘焙”模型单元测试,我得到以下错误。
我认为这是问题:
我们正在使用灯具来添加一些基础数据。这是我认为可能导致问题的唯一地方。为此添加信任,在单元测试运行时,我运行以下命令以获得下一个自动递增id
值并返回1,即使它在非测试数据库中返回了正确的数字。 Select nextval(pg_get_serial_sequence('agencies', 'id')) as new_id;
单元测试:
public function testValidationDefault()
{
$agencyData = [
'full_name' => 'Agency Full Name',
'mode' => 'transit',
'request_api_class' => 'Rest\Get\Json',
'response_api_class' => 'NextBus\Generic',
'realtime_url_pattern' => 'http://api.example.com',
'routes' => '{"123": {"full_route": "123 Full Route", "route_color": "#123456"}}'
];
$agency = $this->Agencies->newEntity($agencyData);
$saved = $this->Agencies->save($agency);
$this->assertInstanceOf('App\Model\Entity\Agency', $saved);
}
错误:
PDOException: SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint "agencies_pkey"
DETAIL: Key (id)=(1) already exists.
我尝试过的事情
此装置确实为每个记录设置了ID字段。从夹具中删除它们确实有效,但它会破坏依赖某些关系数据的其他单元测试。
答案 0 :(得分:4)
我不喜欢这个解决方案,但在保存实体之前添加以下内容确实有效。
$this->Agencies->deleteAll('1=1');
答案 1 :(得分:4)
[更新:我的另一个答案是解决这个问题的真正方法。你不必再这样做了......]
这是一个 less 脏解决方法,不需要删除所有记录:
use Cake\Datasource\ConnectionManager;
...
$connection = ConnectionManager::get('test');
$results = $connection->execute('ALTER SEQUENCE <tablename>_id_seq RESTART WITH 999999');
//TEST WHICH INSERTS RECORD(s)...
在setUp()
或tearDown()
期间,似乎无法正确设置/重置自动递增...因此请手动将其设置为非常高的值(大于现有记录的数量) )防止“重复键...”错误。
此hack(超过deleteAll('1=1')
)的好处是您仍然可以随后运行引用现有数据库数据的测试。
答案 2 :(得分:3)
它可能是您的灯具定义中的问题。 Cake PHP documentation使用_constraints
字段指定id
字段是主键:
'_constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
]
答案 3 :(得分:2)
我相信我终于找到了解决这个问题的真正解决方案!
我认为这个问题源于使用bake
命令生成灯具所导致的默认灯具设置。
当你bake
模型时,它会为它的夹具创建样板。请注意下面代码中ID属性的autoIncrement
?与您的想法相反,这应该不而是true
。当我将其设置为null
并从id
数组中的项目中移除$records
时,我不再会遇到唯一性错误。
public $fields = [
'id' => ['type' => 'integer', 'length' => 10, 'autoIncrement' => true, 'default' => null, 'null' => false, 'comment' => null, 'precision' => null, 'unsigned' => null],
'nickname' => ['type' => 'text', 'length' => null, 'default' => null, 'null' => false, 'comment' => null, 'precision' => null],
...
public $records = [
[
// 'id' => 1,
'nickname' => 'Foo bar',
'width' => 800,
...
CakePHP项目中的忍者向导是英雄:来源 CakePHP ticket
答案 4 :(得分:2)
如果从夹具记录中删除 from mpl_toolkits.basemap import Basemap,cm
import matplotlib.pyplot as plt
import numpy as np
from netCDF4 import Dataset
import arcpy
import os
import datetime
from dateutil.rrule import rrule, DAILY
import netCDF4
directory = 'C:/Users/ma570408/Documents/Dr.WAng/Haiti project/TRMM_Haiti/TRMM3B42/'
os.chdir(directory)
result_array = np.array((0,28))
fl_pfx = 'disc2.gesdisc.eosdis.nasa.gov-3B42_Daily.'
fl_sfx = '.7.nc4'
strt_dt = datetime.date(1998,1,1)
end_dt = datetime.date(1998,1,3)
for day in rrule(DAILY, dtstart=strt_dt, until=end_dt):
day_fmt = datetime.datetime.strftime(day, '%Y%m%d')
src_fl = '{0}{1}{2}'.format(fl_pfx, day_fmt, fl_sfx)
precip = netCDF4.Dataset(src_fl, 'r')
precip = precip.variables['precipitation']
precip = precip[:]
precip = np.transpose(precip)
#precip.close()
theLats = np.arange(-49.875,50,0.25)
theLons = np.arange(-179.875,180,0.25)
# Set all the missing values less than 0 to NaNs
np.putmask(precip,precip<0,np.nan)
# Plot the figure, define the geographic bounds
fig = plt.figure(dpi=300)
latcorners = ([17.25,21.25])
loncorners = ([-75.25,-67.57])
m = Basemap(projection='cyl',llcrnrlat=latcorners[0],urcrnrlat=latcorners[1],llcrnrlon=loncorners[0],urcrnrlon=loncorners[1])
# Draw coastlines, state and country boundaries, edge of map.
m.drawcoastlines()
m.drawstates()
m.drawcountries()
# Draw filled contours.
clevs = np.arange(0,100,0.5)
# Define the latitude and longitude data
x, y = np.float32(np.meshgrid(theLons, theLats))
cs = m.contourf(x,y,precip,clevs,cmap=cm.GMT_drywet,latlon=True)
parallels = np.arange(-50.,51,25.)
m.drawparallels(parallels,labels=[True,False,True,False])
meridians = np.arange(-180.,180.,60.)
m.drawmeridians(meridians,labels=[False,False,False,True])
# Set the title and fonts
plt.title('01 Jan 1998 UTC Rain Rate')
font = {'family' : 'normal', 'weight' : 'bold', 'size' : 4}
plt.rc('font', **font)
# Add colorbar
cbar = m.colorbar(cs,location='right',pad="5%")
cbar.set_label('mm/day')
#plt.show()
#plt.savefig('testTRMMmap.jpg',dpi=300)
lons=[-72.357027,-72.459848,-72.49067 ,-72.682285,-72.338742,-72.483468,-72.375638,-72.625579 ,-72.621485,-72.689335,-72.701488,-72.334749,-72.081942 ,-72.019022, -71.992917 ,-71.950678 ,-71.841423 ,-72.237008 ,-72.15214,-72.178977,-71.825884,-72.12135,-72.271279,-72.192902,-72.107022,-72.126704,-72.397491,-72.529367]
lats=[19.07039,19.218378,19.025554,19.098092,19.34189,19.490445,19.525487,19.493374,19.355849 ,19.310919,19.258246,18.909316,18.785043,19.144316,18.999588,18.866657,18.746084,18.830828,18.952298,19.188401,19.075994,19.464433,19.5202,19.402877,19.324003,18.66134,18.774135,18.88551]
lons=np.array(lons)
lats=np.array(lats)
py = (lons +180) /0.25
px = (lats +50) /0.25
py=py.tolist()
px=px.tolist()
pixel_value=precip[px,py]
pixel_value=np.array(pixel_value).reshape(1,28)
pixel_value=str(pixel_value)
print (pixel_value)
thefile=open('test.txt','w')
thefile.write(pixel_value)
thefile.close()
个字段,那么它们将在插入时使用自动递增,将表的ID序列保留在测试期间发生的插入的正确位置。我相信这就是为什么它适用于@emersonthis,如上所述。
该解决方案还有另一个问题:您无法在夹具记录之间创建可靠的关系,因为您不知道它们将获得哪些ID。你把什么放在相关表的外国ID字段中?这使我回到原来的解决方案,即在插入带有硬编码ID的记录后改变表序列。我现在在受影响的TestCases中这样做:
id
这会将自动增量序列移动到先前使用的最高ID。下一次从序列生成ID时,它将高一个,在所有情况下解决问题。
在即将发布的CakePHP版本中包含其中一个解决方案是being discussed here。